You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
211 lines
5.0 KiB
211 lines
5.0 KiB
'use strict';
|
|
|
|
/**
|
|
*
|
|
*/
|
|
function Mesh() {
|
|
// // Color seed coordinants
|
|
// this.seeds = [];
|
|
|
|
// Length of a side
|
|
this.side = 10;
|
|
|
|
// // How far a seed will extend its reach
|
|
this.seedWeight = 40;
|
|
|
|
//
|
|
this.width = 400;
|
|
this.height = 400;
|
|
|
|
var faces = this.initFaces(this.width, this.height, this.side);
|
|
|
|
this.addSeed(new Seed(0, 0, '#ff0000', this.seedWeight), faces);
|
|
this.addSeed(new Seed(0, 39, '#0000ff', this.seedWeight), faces);
|
|
this.addSeed(new Seed(39, 0, '#00ff00', this.seedWeight), faces);
|
|
this.addSeed(new Seed(39, 39, '#ffff00', this.seedWeight), faces);
|
|
|
|
this.calculateFills(faces);
|
|
|
|
var svg = d3.select("body").append("svg").attr('width', this.width).attr('height', this.height);
|
|
|
|
svg.selectAll('rect')
|
|
.data(faces)
|
|
.enter()
|
|
.append('rect')
|
|
.attr('id', function(d) { return d.id; })
|
|
.attr('x', function(d) { return d.x; })
|
|
.attr('y', function(d) { return d.y; })
|
|
.attr('width', function(d) { return d.side; })
|
|
.attr('height', function(d) { return d.side; })
|
|
.attr('fill', function(d) { return d.fill; })
|
|
.attr('stroke', 0)
|
|
|
|
// d3.select(id).attr('fill', seed.fill);
|
|
// for (var i = 0, len = seeds.length; i < len; i++) {
|
|
// d3.select(seeds[i].faceId).attr('fill', seeds[i].fill);
|
|
// }
|
|
};
|
|
|
|
/**
|
|
*
|
|
*/
|
|
function Face(id, x, y, side) {
|
|
this.id = id;
|
|
this.x = x;
|
|
this.y = y;
|
|
this.side = side;
|
|
this.fill = '#fff';
|
|
this.colors = [];
|
|
};
|
|
|
|
/**
|
|
*
|
|
*/
|
|
function Seed(x, y, fill, weight) {
|
|
this.x = x;
|
|
this.y = y;
|
|
this.fill = fill;
|
|
this.weight = weight;
|
|
};
|
|
|
|
/**
|
|
*
|
|
*/
|
|
Mesh.prototype = {
|
|
/**
|
|
* Faces must be a one dimensional array to pass to D3.
|
|
*/
|
|
initFaces: function(width, height, side) {
|
|
var countW = Math.ceil(width / side);
|
|
var countH = Math.ceil(height / side);
|
|
var all = [];
|
|
|
|
for (var w = 0; w < countW; w++) {
|
|
for (var h = 0; h < countH; h++) {
|
|
all.push(new Face(
|
|
`f-${w}-${h}-${all.length}`,
|
|
w * side,
|
|
h * side,
|
|
side
|
|
));
|
|
}
|
|
}
|
|
|
|
return all;
|
|
},
|
|
|
|
/**
|
|
*
|
|
*/
|
|
calculateFills: function(faces) {
|
|
var len = faces.length;
|
|
var hexes;
|
|
|
|
var populate = function(color) {
|
|
var arr = [];
|
|
for (var k = 0; k < color.weight; k++) {
|
|
arr.push(color.hex);
|
|
}
|
|
return arr;
|
|
};
|
|
|
|
for (var i = 0; i < len; i++) {
|
|
var hexes = [];
|
|
|
|
for (var j = 0; j < faces[i].colors.length; j++) {
|
|
hexes = hexes.concat(populate(faces[i].colors[j]));
|
|
}
|
|
|
|
while (hexes.length < this.seedWeight) {
|
|
hexes.push('#ccccff');
|
|
}
|
|
|
|
faces[i].fill = Compositor.averageHexCollection(hexes);
|
|
}
|
|
},
|
|
|
|
/**
|
|
*
|
|
*/
|
|
addSeed: function(seed, faces) {
|
|
var n = this.seedWeight;
|
|
var len = faces.length;
|
|
var delta, index, weight;
|
|
var countX = this.width / this.side;
|
|
var countY = this.height / this.side;
|
|
|
|
for (var x = (seed.x - n + 1); x < seed.x + n; x++) {
|
|
if (x < 0 || x >= countX) {
|
|
continue;
|
|
}
|
|
|
|
for (var y = (seed.y - n + 1); y < seed.y + n; y++) {
|
|
if (y < 0 || y >= countY) {
|
|
continue;
|
|
}
|
|
|
|
// Diamond shapes around source drop weighting incrementally.
|
|
delta = Math.abs(seed.x - x) + Math.abs(seed.y - y);
|
|
weight = Math.max(0, n - delta);
|
|
|
|
index = x * countY + y;
|
|
|
|
if (weight > 0 && index >= 0 && index < len) {
|
|
faces[index].colors.push({ hex: seed.fill, weight: weight });
|
|
}
|
|
}
|
|
}
|
|
},
|
|
};
|
|
|
|
/**
|
|
*
|
|
*/
|
|
var Compositor = {
|
|
/**
|
|
*
|
|
*/
|
|
averageComponentCollection: function(collection) {
|
|
var len = collection.length;
|
|
var total = 0;
|
|
|
|
for (var i = 0; i < len; i++) {
|
|
total += parseInt(collection[i], 16);
|
|
}
|
|
|
|
var avg = Math.round(total / len);
|
|
avg = avg.toString(16);
|
|
avg = ('00' + avg).slice(-2);
|
|
|
|
return avg;
|
|
},
|
|
|
|
/**
|
|
*
|
|
*/
|
|
averageHexCollection: function(collection) {
|
|
// check hex against regex
|
|
|
|
var allR = [];
|
|
var allG = [];
|
|
var allB = [];
|
|
var len = collection.length;
|
|
var tmp, hex;
|
|
|
|
for (var i = 0; i < len; i++) {
|
|
tmp = collection[i].substr(1);
|
|
|
|
allR.push(tmp.substr(0, 2));
|
|
allG.push(tmp.substr(2, 2));
|
|
allB.push(tmp.substr(4, 2));
|
|
}
|
|
|
|
var r = this.averageComponentCollection(allR);
|
|
var g = this.averageComponentCollection(allG);
|
|
var b = this.averageComponentCollection(allB);
|
|
|
|
return '#' + r + g + b;
|
|
},
|
|
};
|
|
|
|
var mesh = new Mesh();
|
|
|