Skip to content

Instantly share code, notes, and snippets.

@timgluz
Created March 22, 2017 14:52
Show Gist options
  • Save timgluz/910326675df3b71bb19104282cd34594 to your computer and use it in GitHub Desktop.
Save timgluz/910326675df3b71bb19104282cd34594 to your computer and use it in GitHub Desktop.
Midpoint circle algorithm
/// implemention of http://groups.csail.mit.edu/graphics/classes/6.837/F98/Lecture6/circle.html
use std::fs::File;
use std::path::Path;
use image::{self, GenericImage, ImageBuffer, Pixel, Rgba};
struct Point {
x: u32,
y: u32
}
pub struct Picture {
buffer: Box< ImageBuffer<Rgba<u8>, Vec<u8>> >,
height: u32,
width: u32
}
fn set_circle_point(pic: &mut Picture, center_pt: &Point, line_pt: &Point, color: u8){
let act = Rgba::from_channels(255, 0, 0, 255);
let pix = Rgba::from_channels(255, 0, color, 255);
let ref mut buf = &mut pic.buffer;
if line_pt.x == 0 {
buf.put_pixel(center_pt.x, center_pt.y + line_pt.y, act );
buf.put_pixel(center_pt.x, center_pt.y - line_pt.y, pix);
buf.put_pixel(center_pt.x + line_pt.y, line_pt.y, pix);
buf.put_pixel(center_pt.x - line_pt.y, line_pt.y, pix);
} else if line_pt.x == line_pt.y {
buf.put_pixel(center_pt.x + line_pt.x, center_pt.y + line_pt.y, act);
buf.put_pixel(center_pt.x - line_pt.x, center_pt.y + line_pt.y, pix);
buf.put_pixel(center_pt.x + line_pt.x, center_pt.y - line_pt.y, pix);
buf.put_pixel(center_pt.x - line_pt.x, center_pt.y - line_pt.y, pix);
} else if line_pt.x < line_pt.y {
buf.put_pixel(center_pt.x + line_pt.x, center_pt.y + line_pt.y, act);
buf.put_pixel(center_pt.x - line_pt.x, center_pt.y + line_pt.y, pix);
buf.put_pixel(center_pt.x + line_pt.x, center_pt.y - line_pt.y, pix);
buf.put_pixel(center_pt.x - line_pt.x, center_pt.y - line_pt.y, pix);
buf.put_pixel(center_pt.x + line_pt.y, center_pt.y + line_pt.x, pix);
buf.put_pixel(center_pt.x - line_pt.y, center_pt.y + line_pt.x, pix);
buf.put_pixel(center_pt.x + line_pt.y, center_pt.y - line_pt.x, pix);
buf.put_pixel(center_pt.x - line_pt.y, center_pt.y - line_pt.x, pix);
}
}
fn draw(pic: &mut Picture, center_pt: Point, radius: u32, color: u8) {
let mut start_pt = Point {x: 0, y: radius};
let r:i32 = radius as i32;
let mut p:i32 = ( 5 - r * 4) / 4;
set_circle_point(pic, &center_pt, &start_pt, color);
while start_pt.x < start_pt.y {
start_pt.x += 1;
println!("P: {}", p);
if p < 0 {
p += (2 * start_pt.x + 1) as i32;
} else {
start_pt.y -= 1;
p += (2 * ( (start_pt.x as i32) - (start_pt.y as i32) ) + 1) as i32;
}
set_circle_point(pic, &center_pt, &start_pt, color);
}
}
#[test]
fn save_test_image(){
let (w, h) = (512,512);
let mut buf = ImageBuffer::new(w, h);
let mut pic = Picture { buffer: Box::new(buf), width: w, height: h};
let center_point = Point {x: 255, y: 255};
let radius = 128;
let color = 64u8;
draw(&mut pic, center_point, radius, color);
let ref mut fout = File::create(&Path::new("circle.png")).unwrap();
image::ImageRgba8(*pic.buffer).save(fout, image::PNG).unwrap();
assert!(true);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment