Created
December 30, 2018 03:01
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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