Skip to content

Instantly share code, notes, and snippets.

@bcbroom
Created December 30, 2018 03:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bcbroom/c09a0dbbe682fe7bbdf63319ee710f08 to your computer and use it in GitHub Desktop.
Save bcbroom/c09a0dbbe682fe7bbdf63319ee710f08 to your computer and use it in GitHub Desktop.
Trying to work through operations on Voronoi cells and edges. Very rough and needs to be cleaned up.
const canvasSketch = require('canvas-sketch');
const {Delaunay} = require('d3-delaunay');
const {Cell} = require('./cell');
const settings = {
dimensions: [ 2048, 2048 ]
};
const margin = 256;
const pointsMargin = 512;
let points = [];
for (let i = 0; i < 100; i++) {
const x = Math.random() * 1024 + 512;
const y = Math.random() * 1024 + 512;
points.push([x, y]);
}
let delaunay = Delaunay.from(points);
let voronoi = delaunay.voronoi([margin, margin, 2048 - margin, 2048 - margin]);
let polygons = Array.from(voronoi.cellPolygons());
// recalc points
for (let k=0; k<2; k++) {
let newPoints = [];
for (let i=0; i<polygons.length; i++) {
newPoints.push(centroid(polygons[i]));
}
points = newPoints;
delaunay = Delaunay.from(points);
voronoi = delaunay.voronoi([margin, margin, 2048 - margin, 2048 - margin]);
polygons = Array.from(voronoi.cellPolygons());
}
const minX = voronoi.xmin;
const minY = voronoi.ymin;
const maxX = voronoi.xmax;
const maxY = voronoi.ymax;
const border = 20;
let cells = [];
polygons = Array.from(voronoi.cellPolygons());
for (let i=0; i<polygons.length; i++) {
let cell = new Cell(i);
for (const p of polygons[i]) {
if (p[0] - minX < border || maxX - p[0] < border ||
p[1] - minY < border || maxY - p[1] < border) {
cell.isWater = true;
}
cells.push(cell);
}
}
const testX = 1024; //Math.floor(Math.random() * 1024 + 512);
const testY = 1024; //Math.floor(Math.random() * 1024 + 512);
const testPoint = [testX, testY];
const testIndex = delaunay.find(testPoint[0], testPoint[1]);
const neighbors = Array.from(delaunay.neighbors(testIndex));
const whichNeighbor = 2;
const sketch = () => {
return ({ context, width, height }) => {
context.fillStyle = 'white';
context.fillRect(0, 0, width, height);
context.strokeStyle = 'cornsilk';
context.lineWidth = 4;
const waterFill = 'blue';
const groundFill = 'tan';
const pointFill = 'yellow';
for (const cell of cells) {
context.beginPath();
voronoi.renderCell(cell.index, context);
if (cell.isWater) {
context.fillStyle = waterFill;
context.fill();
context.strokeStyle = 'CadetBlue';
context.stroke();
} else {
context.fillStyle = groundFill;
if (cell.index == testIndex) {
context.fillStyle = 'green';
}
if (neighbors.includes(cell.index)) {
context.fillStyle = 'orange';
}
if (cell.index == neighbors[whichNeighbor]) {
context.fillStyle = 'lightgreen';
}
context.fill();
context.strokeStyle = 'cornsilk';
context.stroke();
const px = delaunay.points[2 * cell.index];
const py = delaunay.points[2 * cell.index + 1];
context.beginPath();
context.arc(px, py, 4, 0, Math.PI * 2, true);
context.fillStyle = pointFill;
context.fill();
}
}
// const testX = 1024; //Math.floor(Math.random() * 1024 + 512);
// const testY = 1024; //Math.floor(Math.random() * 1024 + 512);
// const testPoint = [testX, testY];
// const testIndex = delaunay.find(testPoint[0], testPoint[1]);
// const neighbors = Array.from(delaunay.neighbors(testIndex));
let ei = delaunay.inedges[testIndex];
let ej = delaunay.halfedges[ei];
// should be in a loop, but just testing
// this is nextHalfEdge
// first iteration is different? example has do-while
if (whichNeighbor != 0) {
ei = (ei % 3 === 2) ? ei - 2 : ei + 1;
ej = delaunay.halfedges[ei];
}
for (let n=0; n<whichNeighbor-1; n++) {
ei = (ej % 3 === 2) ? ej - 2 : ej + 1;
ej = delaunay.halfedges[ei];
}
const tei = delaunay.triangles[ei];
const tej = delaunay.triangles[ej];
// floor to make sure starting on the first index of triplet
const ti = Math.floor(ei/3);
const ti0 = delaunay.triangles[ti*3];
const ti1 = delaunay.triangles[ti*3 + 1];
const ti2 = delaunay.triangles[ti*3 + 2];
const tj = Math.floor(ej/3);
const tj0 = delaunay.triangles[tj*3];
const tj1 = delaunay.triangles[tj*3+1];
const tj2 = delaunay.triangles[tj*3+2];
context.beginPath();
context.lineTo(delaunay.points[ti0*2], delaunay.points[ti0*2+1]);
context.lineTo(delaunay.points[ti1*2], delaunay.points[ti1*2+1]);
context.lineTo(delaunay.points[ti2*2], delaunay.points[ti2*2+1]);
context.closePath();
context.stroke();
context.beginPath();
context.lineTo(delaunay.points[tj0*2], delaunay.points[tj0*2+1]);
context.lineTo(delaunay.points[tj1*2], delaunay.points[tj1*2+1]);
context.lineTo(delaunay.points[tj2*2], delaunay.points[tj2*2+1]);
context.closePath();
context.stroke();
// connect centers of two cells
context.beginPath();
context.lineTo(delaunay.points[tei*2], delaunay.points[tei*2+1]);
context.lineTo(delaunay.points[tej*2], delaunay.points[tej*2+1]);
context.lineWidth = 8;
context.strokeStyle = 'blue';
context.stroke();
// draw the related edge
const cix = voronoi.circumcenters[ti*2];
const ciy = voronoi.circumcenters[ti*2+1];
const cjx = voronoi.circumcenters[tj*2];
const cjy = voronoi.circumcenters[tj*2+1];
context.beginPath();
context.lineTo(cix, ciy);
context.lineTo(cjx, cjy);
context.strokeStyle = 'red';
context.stroke();
};
};
canvasSketch(sketch, settings);
function centroid(poly) {
let x = 0;
let y = 0;
for (let i=0; i<poly.length-1; i++) {
x += poly[i][0];
y += poly[i][1];
}
x /= (poly.length - 1);
y /= (poly.length - 1);
return([x, y]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment