Pixel scanning of a moving arc
in
Programming Questions
•
1 year ago
I am trying to build a kaleidoscope where a use can drag shapes into a circle canvas and whatever is in that canvas will be translated into the kaleidoscope output. An arc in the canvas will rotate and scan a 45 degree fragment of the canvas which will be used for the output. However I am stumped on an efficient algorithm to scan all the pixels in the arc without any slowdown. Does anyone have any input on how to scan the pixels in an arc area and translate them to another area without much slowdown?
Canvas canvas;
Palette palette;
Kaleidoscope kaleidoscope;
void setup(){
size(1240, 768, P2D);
//smooth();
canvas = new Canvas();
kaleidoscope = new Kaleidoscope();
palette = new Palette();
}
void draw(){
background(0);
canvas.display();
palette.display();
kaleidoscope.display();
}
///////////////////////////////////////////////////////////////////////////////////////////////
// Kaleidoscope - displays the translated mapping
///////////////////////////////////////////////////////////////////////////////////////////////
class Kaleidoscope extends Wedge {
float kDiameter = 500;
PVector location = new PVector(800, height/2);;
ArrayList slices = new ArrayList();
float angle;
Kaleidoscope(){
// construct the slices
for(int i = 0; i < 8; i++){
angle += radians(45);
}
}
void display(){
//fill(0,0,255);
noFill();
stroke(255);
ellipse(location.x, location.y, kDiameter, kDiameter);
// Display the mapped wedge
// experimental: just used to show that the pixel map can be transferred
// to a different location
if(canvas.wedge.wedgeMap.size() > 0){
int count = 0;
for(int i = 0; i < int(canvas.cDiameter/2); i++){
float j = canvas.wedge.leftAngle;
PVector lastP = new PVector(0,0);
while(j < canvas.wedge.rightAngle){
PVector p = new PVector(location.x+(i*cos(j)), location.y+(i*sin(j)));
int k = (int)(p.y*width+p.x);
fill((Integer)canvas.wedge.wedgeMap.get(count));
stroke((Integer)canvas.wedge.wedgeMap.get(count));
point(p.x, p.y);
endShape();
count++;
j += 0.01;
}
}
}
}
}
///////////////////////////////////////////////////////////////////////////////////////////////
// Wedge - the scanning arc
///////////////////////////////////////////////////////////////////////////////////////////////
class Wedge {
float leftAngle;
float rightAngle;
ArrayList<Integer> wedgeMap = new ArrayList<Integer>();
Wedge(){
leftAngle = 0;
rightAngle = PI/4;
}
void display(){
fill(255, 255, 0);
arc(canvas.location.x, canvas.location.y, canvas.cDiameter, canvas.cDiameter, leftAngle, rightAngle);
}
void scan(){
wedgeMap.clear();
int cRadius = (int)canvas.cDiameter/2;
PVector c = canvas.location;
// Begin live mapping
loadPixels();
for(int i = 0; i < cRadius; i++){
float j = leftAngle;
while(j < rightAngle){
PVector p = new PVector(c.x+(i*cos(j)), c.y+(i*sin(j)));
int k = (int)(p.y*width+p.x);
wedgeMap.add(pixels[k]);
j += 0.01;
}
}
updatePixels();
rotateWedge(0.01);
}
void rotateWedge(float rate){
rightAngle += rate;
leftAngle += rate;
}
}
///////////////////////////////////////////////////////////////////////////////////////////////
// Fruit - the things being used to drag into the canvas
///////////////////////////////////////////////////////////////////////////////////////////////
class Fruit {
HashMap fruits = new HashMap<String, PImage>();
PImage img;
PVector location;
float scaling;
boolean isSelected = false;
Fruit(String type, PVector location, float scaling){
fruits.put("apple", loadImage("processing.png"));
fruits.put("orange", loadImage("processing.png"));
img = (PImage) fruits.get(type);
this.location = location;
this.scaling = scaling;
}
Fruit(){
fruits.put("apple", loadImage("processing.png"));
fruits.put("orange", loadImage("processing.png"));
}
void display(){
pushMatrix();
if(isSelected) location = new PVector(mouseX, mouseY);
translate(location.x, location.y);
scale(scaling);
image(img, -img.width/2, -img.height/2);
popMatrix();
}
}
///////////////////////////////////////////////////////////////////////////////////////////////
// Canvas - where items will be dragged into and where the wedge scans
///////////////////////////////////////////////////////////////////////////////////////////////
class Canvas {
Wedge wedge = new Wedge();
PVector location = new PVector(250, height/2);
float cDiameter = 500;
HashMap<PVector, Integer> pixelMap = new HashMap<PVector, Integer>();
Canvas(){
}
void display(){
pushMatrix();
fill(255);
rect(300,500,50,50);
popMatrix();
fill(255, 0,0);
stroke(255, 0, 0);
ellipse(location.x, location.y, cDiameter, cDiameter);
//scan first so it doesnt pick up the display overlay color
wedge.scan();
wedge.display();
}
// Maps the entire canvas
void mapCanvas(){
float sqRadius=sq(cDiameter/2);
for(int x=-floor((cDiameter/2f)+location.x);x<=ceil((cDiameter/2f)+location.x);x++){
for(int y=-floor((cDiameter/2f)+location.x);y<=ceil((cDiameter/2f)+location.x);y++){
if(sq(x)+sq(y) <= sqRadius){
pixelMap.put(new PVector(x+location.x, y+location.y), get(round(x+location.x), round(y+location.y)));
}
}
}
}
}
///////////////////////////////////////////////////////////////////////////////////////////////
// Palette
///////////////////////////////////////////////////////////////////////////////////////////////
class Palette {
ArrayList<Fruit> fruits = new ArrayList<Fruit>();
Palette(){
fruits.add(new Fruit("apple", new PVector(150, 150), 0.5));
}
void display(){
((Fruit)fruits.get(0)).display();
}
}
///////////////////////////////////////////////////////////////////////////////////////////////
// Mouse Functions
///////////////////////////////////////////////////////////////////////////////////////////////
void mouseDragged() {
// Determine if the user has touched something in the palette
for(Fruit fruit : palette.fruits){
if(mouseX > fruit.location.x && mouseX < fruit.location.x + fruit.img.width &&
mouseY > fruit.location.y && mouseY < fruit.location.y + fruit.img.height){
fruit.isSelected = true;
}
}
}
void mouseReleased() {
for(Fruit fruit : palette.fruits){
fruit.isSelected = false;
}
//canvas.mapCanvas();
//canvas.wedge.scan();
}
Thanks in advance for any help :)
1