xxxxxxxxxx
422
/*
really happy with how this turned out
was a lot more effort than i thought it would be but now im so invested i wanna do more with it
maybe other ways to make it interactive would be cool
really the voronoi itself was the only hard part now i can do anything with it that does something to points in a grid
*/
let portionOfPoints = 1;
let csvfilename = 'ant4.csv';
let p = [];
let colorFromSize=true;
let userinput = true;
let shift = 2
let polopacity = 255;
let colorScheme = 'bw'; // black, bw, monochrome or color
// the hague yellow
const col = {
h: 48,
s: 97,
b: 93
}
const devRange = {
h: 0,
s: 100,
b: 0
}
const drawStroke = true;
let loopWalls = true;
let drawline = false;
let drawinsec = false;
let colors = [];
let polygons = [];
const markersize = 5;
let off = 0.0;
let table;
function preload(){
table = loadTable(csvfilename, 'csv', 'header');
}
function setup() {
createCanvas(600, 600);
background(255);
noCursor();
numberOfPoints = floor(table.getRowCount() / portionOfPoints);
// generate random points
for(let i=0; i<numberOfPoints*portionOfPoints; i+=portionOfPoints){
// p.push([random(width), random(height)]);
p.push([table.getNum(i,0) * 4 + random(0.1),table.getNum(i,1) * 4 + random(0.1)]);
if(colorScheme == 'bw'){
colors.push(50 + i*(150/numberOfPoints));
}
else if(colorScheme == 'black'){
colors.push(0);
}
else if(colorScheme == 'monochrome'){
colorMode(HSB, 360, 100, 100, 1);
colors.push([col.h + random(devRange.h)-devRange.h/2,
col.s + random(devRange.s)-devRange.s/2,
col.b + random(devRange.b)-devRange.b/2])
}
else{
colors.push([random(255),random(255),random(255)])
}
}
print(colors);
for(let i=0; i<numberOfPoints; i++){
for(let j=0; j<numberOfPoints; j++){
if((p[i][0] == p[j][0] || p[i][1] == p[j][1]) && i!=j){
print('DOUBLE VALUE!')
}
}
}
createVoronoi();
if(colorFromSize){
for(let i = 0; i<polygons.length; i++){
let circumference = 0;
for(let j=0; j<polygons[i].length-1; j++){
circumference +=dist(polygons[i][j][0], polygons[i][j][1], polygons[i][j+1][0], polygons[i][j+1][1]);
}
colors[i] = circumference;
}
let power = 0.5;
let multiplier = 255/(max(colors)**power)
for(let i = 0; i<polygons.length; i++){
colors[i] = colors[i] ** power * multiplier;
}
}
drawPolygons();
// drawPoints();
}
function createVoronoi(){
polygons = [];
//draw points
// drawPoints();
for(let a=0;a<p.length;a++){
//draw lines for all other points
let c = [];
let s = [];
let my = []; // on which side of line is point
let mx = []; // where is the middle x of the line
let pdist = sqrt(width**2 + height**2);
let curint;
for(let b=0;b<p.length;b++){
if(b!=a){
c[b] = ((p[b][0]-p[a][0]) / (p[a][1]-p[b][1]));
s[b] = ((p[a][1]+p[b][1])/2 - c[b] * (p[a][0]+p[b][0]) / 2);
//AB = c*x + s
my[b] = (p[a][1] + p[b][1]) / 2; //1 if a is right of b, -1 if a is left
mx[b] = (p[a][0] + p[b][0]) / 2;
if(sqrt((p[a][0]-p[b][0])**2 + (p[a][1]-p[b][1])**2) < pdist){
pdist = sqrt((p[a][0]-p[b][0])**2 + (p[a][1]-p[b][1])**2);
curint = b;
}
}
else{
c[b] = 'n/a';
s[b] = 'n/a';
my[b] = 'n/a';
mx[b] = 'n/a';
}
}
my.push((0+p[a][1])/2, (height+p[a][1])/2, p[a][1], p[a][1]);
mx.push(p[a][0], p[a][0], (0+p[a][0])/2, (width+p[a][0])/2);
//create array to store polygon points
let pol = [];
if(drawline){
drawLines(c,s);
}
// find intersections with current line
let insec = findLineIntersections(curint,c,s);
if(drawinsec){
drawIntersections(insec);
}
//find closest intersection
let closestInt = findHorInt(Math.sign((mx[curint] - p[a][0]) * c[curint] * -1), mx[curint], insec);
pol.push(closestInt[0]);
curint = closestInt[1];
//start looping through the points
findPolygonLoop(a, c, s, mx, my, pol, insec, curint);
polygons.push(pol);
}
}
function findPolygonLoop(a, c, s, mx, my, pol, insec, curint){
if(curint >= c.length){
//its one of the borders
insec = findBorderIntersections(curint - c.length, c, s);
}
else{
//its with another line
insec = findLineIntersections(curint, c, s);
}
//draw intersections
// drawIntersections(insec);
//find closest intersection in the correct direction
let closestInt;
if(curint >= c.length){
if(curint > c.length + 1){
//vertical border
closestInt = findVertInt(1 - 2* (curint-c.length-2), pol[pol.length-1][1], insec, c);
}
else{
//horizontal border
closestInt = findHorInt( 2* (curint-c.length) -1, pol[pol.length-1][0], insec);
}
}
else{
//normal line always works like this?
closestInt = findHorInt(Math.sign((mx[curint] - p[a][0]) * c[curint] * -1), pol[pol.length-1][0], insec);
// closestInt = findHorInt(Math.sign(-p[a][1] + p[curint][1]), pol[pol.length-1][0], insec);
}
if(pol[0][0] != closestInt[0][0] || pol[0][1] !=closestInt[0][1] ){
pol.push(closestInt[0]);
curint = closestInt[1];
findPolygonLoop(a, c, s, mx, my, pol, insec, curint);
}
else{
}
}
function findLineIntersections(l1,c,s){
let xint = [], yint = [];
for(let l=0;l<c.length;l++){
if(l!=l1 && c[l] != 'n/a'){
xint[l] = ( (s[l] - s[l1]) / (c[l1] - c[l]) );
yint[l] = (c[l1] * xint[l] + s[l1]);
}
else{
xint[l] = 'n/a';
yint[l] = 'n/a'
}
}
//add intersections with borders in order T,B,L,R
xint.push( (0 - s[l1])/c[l1], (height - s[l1])/c[l1], 0, width );
yint.push(0, height, s[l1], c[l1] * width + s[l1]);
let intersections = [];
for(let i=0;i<xint.length;i++){
intersections.push([xint[i], yint[i]])
}
return intersections;
}
function findBorderIntersections(b,c,s){
if(b<2){
//top or bottom
let xint = [];
for(let l=0;l<c.length;l++){
if(c[l] != 'n/a'){
xint[l] = (height*b - s[l])/c[l];
}
else{
xint[l] = 'n/a';
}
}
//add intersections with borders in order T,B,L,R
xint.push( 'n/a', 'n/a', 0, width );
let intersections = [];
for(let i=0;i<xint.length;i++){
if(xint[i] != 'n/a'){
intersections.push([xint[i], height*b]);
}
else{
intersections.push(['n/a','n/a']);
}
}
return intersections;
}
else{
//left or right
let yint = [];
for(let l=0;l<c.length;l++){
if(c[l] != 'n/a'){
yint[l] = width*(b-2)*c[l] + s[l];
}
else{
yint[l] = 'n/a';
}
}
//add intersections with borders in order T,B,L,R
yint.push( 0, height, 'n/a', 'n/a' );
let intersections = [];
for(let i=0;i<yint.length;i++){
if(yint[i] != 'n/a'){
intersections.push([width*(b-2), yint[i]]);
}
else{
intersections.push(['n/a','n/a']);
}
}
return intersections;
}
}
function findHorInt(ms, pnt, insec){
//use this one normally
let curdist = sqrt(width**2 + height**2);
let curint;
for(let i=0; i<insec.length; i++){
if(abs(pnt - insec[i][0]) < curdist &&
Math.sign(insec[i][0] - pnt) == ms ){
curdist = abs(pnt - insec[i][0]);
curint = i;
}
}
return [[insec[curint][0], insec[curint][1]], curint];
}
function findVertInt(ms, pnt, insec, c){
//use this one if on a vertical borderline and/or if previous line was horizontal
let curdist = sqrt(width**2 + height**2);
let curint;
for(let i=0; i<insec.length; i++){
if(abs(pnt - insec[i][1]) < curdist &&
Math.sign(insec[i][1] - pnt) == ms){
curdist = abs(pnt - insec[i][1]);
curint = i;
}
}
return [[insec[curint][0], insec[curint][1]], curint];
}
function drawIntersections(insec){
for(let i=0; i<insec.length; i++){
if(insec[i][0] != 'n/a'){
drawMarker(insec[i][0], insec[i][1], 150);
}}
}
function drawLines(c,s){
stroke(0);
for(let l=0;l<c.length;l++){
if(c[l] != 'n/a'){
line(0,c[l]*0+s[l],width,c[l]*height+s[l]);
}
}
noStroke();
}
function drawPolygons(){
if(drawStroke){
stroke(255);
}
for(let i = 0; i<polygons.length; i++){
if(colorScheme == 'black' || colorScheme == 'bw'){
fill(colors[i], polopacity);
}
else{
fill(colors[i][0],colors[i][1],colors[i][2], polopacity);
}
beginShape()
for(let j=0; j<polygons[i].length; j++){
vertex(polygons[i][j][0], polygons[i][j][1])
}
endShape(CLOSE)
}
noStroke();
}
function drawPoints(){
for(let a=0;a<p.length;a++){
drawMarker(p[a][0],p[a][1],0);
}
}
function drawMarker(x, y, col) {
stroke(col);
line(x - markersize, y, x + markersize, y);
line(x, y - markersize, x, y + markersize);
noStroke();
}
function draw(){
// background(255);
// createVoronoi();
// drawPolygons();
// // drawPoints();
}