June 2018 Update

This commit is contained in:
Ingy döt Net 2018-06-22 20:57:24 +00:00
parent ba8067c3b7
commit 22f33d4004
5278 changed files with 84726 additions and 14379 deletions

View file

@ -0,0 +1,13 @@
using Images
function voronoi(w, h, n_centroids)
dist = (point,vector) -> sqrt.((point[1].-vector[:,1]).^2 .+ (point[2].-vector[:,2]).^2)
dots = [rand(1:h, n_centroids) rand(1:w, n_centroids) rand(RGB{N0f8}, n_centroids)]
img = zeros(RGB{N0f8}, h, w)
for x in 1:h, y in 1:w
distances = dist([x,y],dots) # distance
nn = findmin(distances)[2]
img[x,y] = dots[nn,:][3]
end
return img
end
img = voronoi(800, 600, 200)

View file

@ -0,0 +1,21 @@
using TestImages, Images
function voronoi_img!(img, n_centroids)
n,m = size(img)
w = minimum([n,m])
dist = (point,vector) -> sqrt.((point[1].-vector[:,1]).^2 .+ (point[2].-vector[:,2]).^2)
dots = [rand(1:n, n_centroids) rand(1:m, n_centroids)]
c = []
for i in 1:size(dots,1)
p = dots[i,:]
append!(c, [img[p[1],p[2]]])
end
dots = [dots c]
for x in 1:n, y in 1:m
distances = dist([x,y],dots) # distance
nn = findmin(distances)[2]
img[x,y] = dots[nn,:][3]
end
end
img = testimage("mandrill")
voronoi_img!(img, 300)

View file

@ -0,0 +1,46 @@
use Image::PNG::Portable;
my @bars = ''.comb;
my %type = ( # Voronoi diagram type distance calculation
'Taxicab' => sub ($px, $py, $x, $y) { ($px - $x).abs + ($py - $y).abs },
'Euclidean' => sub ($px, $py, $x, $y) { ($px - $x)² + ($py - $y)² },
'Minkowski' => sub ($px, $py, $x, $y) { ($px - $x)³.abs + ($py - $y)³.abs },
);
my $width = 400;
my $height = 400;
my $dots = 30;
my @domains = map { Hash.new(
'x' => (5..$width-5).roll,
'y' => (5..$height-5).roll,
'rgb' => [(64..255).roll xx 3]
) }, ^$dots;
for %type.keys -> $type {
print "\nGenerating $type diagram... ", ' ' x @bars;
my $img = voronoi(@domains, :w($width), :h($height), :$type);
@domains.map: *.&dot($img);
$img.write: "Voronoi-{$type}-perl6.png";
}
sub voronoi (@domains, :$w, :$h, :$type) {
my $png = Image::PNG::Portable.new: :width($w), :height($h);
for ^$w -> $x {
print "\b" x 2+@bars, @bars.=rotate(1).join , ' ';
for ^$h -> $y {
my ($, $i) = min @domains.map: { %type{$type}(%($_)<x>, %($_)<y>, $x, $y), $++ };
$png.set: $x, $y, |@domains[$i]<rgb>
}
}
$png
}
sub dot (%h, $png, $radius = 3) {
for %h<x> - $radius .. %h<x> + $radius -> $x {
for %h<y> - $radius .. %h<y> + $radius -> $y {
$png.set($x, $y, 0, 0, 0) if ( %h<x> - $x + (%h<y> - $y) * i ).abs <= $radius;
}
}
}

View file

@ -0,0 +1,124 @@
# Project : Voronoi diagram
# Date : 2018/03/30
# Author : Gal Zsolt [~ CalmoSoft ~]
# Email : <calmosoft@gmail.com>
load "guilib.ring"
load "stdlib.ring"
paint = null
new qapp
{
spots = 100
leftside = 400
rightside = 400
locx = list(spots)
locy = list(spots)
rgb = newlist(spots,3)
seal = newlist(leftside, rightside)
reach = newlist(leftside, rightside)
win1 = new qwidget() {
setwindowtitle("Voronoi diagram")
setgeometry(100,100,800,600)
label1 = new qlabel(win1) {
setgeometry(10,10,800,600)
settext("")
}
new qpushbutton(win1) {
setgeometry(150,550,100,30)
settext("draw")
setclickevent("draw()")
}
show()
}
exec()
}
func draw
p1 = new qpicture()
color = new qcolor() {
setrgb(0,0,255,255)
}
pen = new qpen() {
setcolor(color)
setwidth(1)
}
paint = new qpainter() {
begin(p1)
setpen(pen)
for i =1 to spots
locx[i] = floor(leftside * randomf())
locy[i] = floor(rightside * randomf())
rgb[i][1] = floor(256 * randomf())
rgb[i][2] = floor(256 * randomf())
rgb[i][3] = floor(256 * randomf())
next
for x = 1 to leftside
for y = 1 to rightside
reach[x][y] = pow((locx[1] - x),2) + pow((locy[1] - y),2)
seal[x][y] = 1
next
next
for i = 2 to spots
for x = locx[i] to 0 step -1
if not (chkpos(i,x,1, rightside-1))
exit
ok
next
for x = locx[i] + 1 to leftside - 1
if not (chkpos(i, x, 1, rightside-1))
exit
ok
next
next
for x = 1 to leftside
for y = 1 to rightside
c1 = rgb[seal[x][y]][1]
c2 = rgb[seal[x][y]][2]
c3 = rgb[seal[x][y]][3]
color = new qcolor() { setrgb(c1,c2,c3,255) }
pen = new qpen() { setcolor(color) setwidth(10) }
setpen(pen)
starty = y
nearest = seal[x][y]
for y = (y + 1) to rightside
if seal[x][y] != nearest
y = y - 1
exit
ok
next
paint.drawline(x,starty,x,y + 1)
next
next
endpaint()
}
label1 { setpicture(p1) show() }
return
func chkpos(site,x,starty,endy)
chkpos = 0
dxsqr = 0
dxsqr = pow((locx[site]- x),2)
for y = starty to endy
dsqr = pow((locy[site] - y),2) + dxsqr
if x <= leftside and y <= leftside and x > 0 and y > 0
if dsqr <= reach[x][y]
reach[x][y] = dsqr
seal[x][y] = site
chkpos = 1
ok
ok
next
return chkpos
func randomf()
decimals(10)
str = "0."
for i = 1 to 10
nr = random(9)
str = str + string(nr)
next
return number(str)

View file

@ -0,0 +1,180 @@
extern crate piston;
extern crate opengl_graphics;
extern crate graphics;
extern crate touch_visualizer;
#[cfg(feature = "include_sdl2")]
extern crate sdl2_window;
extern crate getopts;
extern crate voronoi;
extern crate rand;
use touch_visualizer::TouchVisualizer;
use opengl_graphics::{ GlGraphics, OpenGL };
use graphics::{ Context, Graphics };
use piston::window::{ Window, WindowSettings };
use piston::input::*;
use piston::event_loop::*;
#[cfg(feature = "include_sdl2")]
use sdl2_window::Sdl2Window as AppWindow;
use voronoi::{voronoi, Point, make_polygons};
use rand::Rng;
static DEFAULT_WINDOW_HEIGHT: u32 = 600;
static DEFAULT_WINDOW_WIDTH: u32 = 600;
struct Settings {
lines_only: bool,
random_count: usize
}
fn main() {
let args: Vec<String> = std::env::args().collect();
let mut opts = getopts::Options::new();
opts.optflag("l", "lines_only", "Don't color polygons, just outline them");
opts.optopt("r", "random_count", "On keypress \"R\", put this many random points on-screen", "RANDOMCOUNT");
let matches = opts.parse(&args[1..]).expect("Failed to parse args");
let settings = Settings{
lines_only: matches.opt_present("l"),
random_count: match matches.opt_str("r") {
None => { 50 },
Some(s) => { s.parse().expect("Random count of bad format") }
}
};
event_loop(&settings);
}
fn random_point() -> [f64; 2] {
[rand::thread_rng().gen_range(0., DEFAULT_WINDOW_HEIGHT as f64), rand::thread_rng().gen_range(0., DEFAULT_WINDOW_WIDTH as f64)]
}
fn random_color() -> [f32; 4] {
[rand::random::<f32>(), rand::random::<f32>(), rand::random::<f32>(), 1.0]
}
fn random_voronoi(dots: &mut Vec<[f64;2]>, colors: &mut Vec<[f32;4]>, num: usize) {
dots.clear();
colors.clear();
for _ in 0..num {
dots.push(random_point());
colors.push(random_color());
}
}
fn event_loop(settings: &Settings) {
let opengl = OpenGL::V3_2;
let mut window: AppWindow = WindowSettings::new("Interactive Voronoi", [DEFAULT_WINDOW_HEIGHT, DEFAULT_WINDOW_WIDTH])
.exit_on_esc(true).opengl(opengl).build().unwrap();
let ref mut gl = GlGraphics::new(opengl);
let mut touch_visualizer = TouchVisualizer::new();
let mut events = Events::new(EventSettings::new().lazy(true));
let mut dots = Vec::new();
let mut colors = Vec::new();
let mut mx = 0.0;
let mut my = 0.0;
while let Some(e) = events.next(&mut window) {
touch_visualizer.event(window.size(), &e);
if let Some(button) = e.release_args() {
match button {
Button::Keyboard(key) => {
if key == piston::input::keyboard::Key::N { dots.clear(); colors.clear(); }
if key == piston::input::keyboard::Key::R { random_voronoi(&mut dots, &mut colors, settings.random_count); }
}
Button::Mouse(_) => {
dots.push([mx, my]);
colors.push(random_color());
},
_ => ()
}
};
e.mouse_cursor(|x, y| {
mx = x;
my = y;
});
if let Some(args) = e.render_args() {
gl.draw(args.viewport(), |c, g| {
graphics::clear([1.0; 4], g);
let mut vor_pts = Vec::new();
for d in &dots {
vor_pts.push(Point::new(d[0], d[1]));
}
if vor_pts.len() > 0 {
let vor_diagram = voronoi(vor_pts, DEFAULT_WINDOW_WIDTH as f64);
let vor_polys = make_polygons(&vor_diagram);
for (i, poly) in vor_polys.iter().enumerate() {
if settings.lines_only {
draw_lines_in_polygon(poly, &c, g);
} else {
draw_polygon(poly, &c, g, colors[i]);
}
}
}
for d in &dots {
draw_ellipse(&d, &c, g);
}
});
}
}
}
fn draw_lines_in_polygon<G: Graphics>(
poly: &Vec<Point>,
c: &Context,
g: &mut G,
)
{
let color = [0.0, 0.0, 1.0, 1.0];
for i in 0..poly.len()-1 {
graphics::line(
color,
2.0,
[poly[i].x.into(), poly[i].y.into(), poly[i+1].x.into(), poly[i+1].y.into()],
c.transform,
g
)
}
}
fn draw_polygon<G: Graphics>(
poly: &Vec<Point>,
c: &Context,
g: &mut G,
color: [f32; 4]
) {
let mut polygon_points: Vec<[f64; 2]> = Vec::new();
for p in poly {
polygon_points.push([p.x.into(), p.y.into()]);
}
graphics::polygon(
color,
polygon_points.as_slice(),
c.transform,
g
)
}
fn draw_ellipse<G: Graphics>(
cursor: &[f64; 2],
c: &Context,
g: &mut G,
) {
let color = [0.0, 0.0, 0.0, 1.0];
graphics::ellipse(
color,
graphics::ellipse::circle(cursor[0], cursor[1], 4.0),
c.transform,
g
);
}