xxxxxxxxxx
/******************
Code by Vamoss
Original code link:
https://openprocessing.org/sketch/1238657
Author links:
http://vamoss.com.br
http://twitter.com/vamoss
http://github.com/vamoss
******************/
const total = 8000;
const relaxInterations = 10;
var img;
var delaunay;
var voronoi;
var cachedBrightness;
var points = new Float64Array(total * 2);
const closest = new Float64Array(total * 2);
const weights = new Float64Array(total);
var TSP;
var solution;
var done = false;
let svgCanvas;
let drawMode = 1;
let penWidth = 1;
function preload() {
img = loadImage('foto profilo.jpg');
}
function setup() {
createCanvas(img.width, img.height);
svgCanvas = createGraphics(img.width, img.height, SVG);
svgCanvas.id('svgCanvas');
svgCanvas.style('display', 'block');
svgCanvas.addClass('center-screen');
svgCanvas.clear();
img.loadPixels();
cachedBrightness = new Float64Array(img.width * img.height);
for (var y = 0, i = 0; y < img.height; y++) {
for (var x = 0; x < img.width; x++) {
var index = y * img.width + x;
// 1 controls the contrast, change alpha channel
cachedBrightness[index] = 1 - red(img.get(x, y)) / 255;
}
}
var i = 0;
while (i < total) {
var x = round(random(img.width));
var y = round(random(img.height));
var index = y * img.width + x;
if (Math.random() < cachedBrightness[index]) {
points[i * 2 + 0] = x;
points[i * 2 + 1] = y;
i++;
}
}
delaunay = new Delaunay(points);
voronoi = delaunay.voronoi([0, 0, img.width, img.height]);
}
function draw() {
background(255);
if (frameCount < relaxInterations) {
/*
this.drawingContext.beginPath();
voronoi.render(this.drawingContext);
this.drawingContext.strokeStyle = "red";
this.drawingContext.stroke();
*/
// Compute the weighted centroid for each Voronoi cell.
closest.fill(0);
weights.fill(0);
for (let y = 0, i = 0; y < img.height; ++y) {
for (let x = 0; x < img.width; ++x) {
const w = cachedBrightness[y * img.width + x];
i = delaunay.find(x + 0.5, y + 0.5, i);
weights[i] += w;
closest[i * 2] += w * (x + 0.5);
closest[i * 2 + 1] += w * (y + 0.5);
}
}
// Relax the diagram by moving points to the weighted centroid.
// Wiggle the points a little bit so they don’t get stuck.
const w = Math.pow(frameCount + 1, -0.8) * 10;
for (let i = 0; i < total; ++i) {
const x0 = points[i * 2];
const y0 = points[i * 2 + 1];
const x1 = weights[i] ? closest[i * 2] / weights[i] : x0;
const y1 = weights[i] ? closest[i * 2 + 1] / weights[i] : y0;
points[i * 2] = x0 + (x1 - x0) * 1.8 + (Math.random() - 0.5) * w;
points[i * 2 + 1] = y0 + (y1 - y0) * 1.8 + (Math.random() - 0.5) * w;
}
voronoi.update();
//draw points
for (var i = 0; i < total; i++) {
circle(points[i * 2], points[i * 2 + 1], 3);
}
} else if (frameCount == relaxInterations) {
//convert monodimensional interger array[x,y,x,y...]
//to an array of objects [{x,y},{x,y}...]
//and calculate the hilbert value
var arrayOfObjects = [];
const curveSize = pow(2, ceil(Math.log2(max(img.width, img.height))))
for (var i = 0; i < total; i++) {
const x = points[i * 2];
const y = points[i * 2 + 1];
const h = hilbert(x, y, curveSize);
const index = floor(y) * img.width + floor(x);
const w = cachedBrightness[index];
arrayOfObjects.push({
x: x,
y: y,
h: h,
w: w
});
}
points = arrayOfObjects.sort((a, b) => a.h - b.h);
//start TSP
TSP = solveTSP(points);
} else {
var count = 0;
while (!done && count++ < 3) {
var result = TSP.next();
done = result.done;
if (!done) {
solution = result.value;
}
}
switch (drawMode) {
case 1:
svgCanvas.clear()
svgCanvas.noFill();
for (var i = 0; i < solution.length; i++) {
svgCanvas.strokeWeight(penWidth);
svgCanvas.line(points[solution[i]].x,
points[solution[i]].y,
points[solution[(i + 1) % solution.length]].x,
points[solution[(i + 1) % solution.length]].y
);
}
break;
case 2:
noFill();
for (var i = 0; i < solution.length; i++) {
svgCanvas.strokeWeight(penWidth);
svgCanvas.beginShape();
svgCanvas.curveVertex(
points[solution[i]].x,
points[solution[i]].y
);
svgCanvas.curveVertex(
points[solution[(i+2)%solution.length]].x,
points[solution[(i+2)%solution.length]].y
);
svgCanvas.curveVertex(
points[solution[(i+4)%solution.length]].x,
points[solution[(i+4)%solution.length]].y
);
svgCanvas.curveVertex(
points[solution[(i+6)%solution.length]].x,
points[solution[(i+6)%solution.length]].y
);
endShape();
}
break;
}
}
if (done == true) {
console.log('done');
noLoop();
}
}
function keyPressed () {
if (key == 's' || key == 'S' ) {
svgCanvas.saveSVG("giovanni.svg");
}
}