2019-05-29 19:21:03 +00:00
"use strict" ;
2019-06-10 22:24:28 +00:00
import L from 'leaflet' ;
import { Delaunay } from 'd3-delaunay' ;
2019-05-29 20:06:00 +00:00
import Vector2 from '../Helpers/Vector2.mjs' ;
import Rectangle from '../Helpers/Rectangle.mjs' ;
/ * *
* Generates and manages a single voronoi SVGOverlay layer .
* /
2019-05-29 19:21:03 +00:00
class VoronoiOverlay {
constructor ( ) {
2019-05-29 20:06:00 +00:00
this . border = new Vector2 ( 0.1 , 0.1 ) ; // lat / long
this . cells = [ ] ;
}
2019-06-10 23:19:37 +00:00
/ * *
* Adds a cell to the voronoi overlay .
* @ param { VoronoiCell } cells The cell to add . May be specified as many times as requires to add cells in bulk .
* /
2019-05-29 20:06:00 +00:00
addCells ( ... cells ) {
this . cells . push ( ... cells ) ;
}
/ * *
* Computes the bounding box of all the currently registered points .
* Includes a border , which is defined by this . border .
* @ return { Rectangle } The bounding box of the currently registered points .
* /
computeBoundingBox ( ) {
2019-06-10 22:24:28 +00:00
let result = {
x _min : Infinity ,
x _max : - Infinity ,
y _min : Infinity ,
y _max : - Infinity
}
2019-05-29 20:06:00 +00:00
for ( let cell of this . cells ) {
2019-06-10 23:19:37 +00:00
if ( cell . point . x < result . x _min ) result . x _min = cell . point . x ;
if ( cell . point . x > result . x _max ) result . x _max = cell . point . x ;
if ( cell . point . y < result . y _min ) result . y _min = cell . point . y ;
if ( cell . point . y > result . y _max ) result . y _max = cell . point . y ;
2019-05-29 20:06:00 +00:00
}
2019-05-29 19:21:03 +00:00
2019-06-10 22:24:28 +00:00
result . x _min -= this . border . x ;
result . y _min -= this . border . y ;
result . x _max += this . border . x ;
result . y _max += this . border . y ;
2019-05-29 20:06:00 +00:00
2019-06-10 22:24:28 +00:00
return new Rectangle (
result . x _min ,
result . y _min ,
result . x _max - result . x _min ,
result . y _max - result . y _min
) ;
2019-05-29 20:06:00 +00:00
}
render ( ) {
let bounding _box = this . computeBoundingBox ( ) ;
2019-06-10 22:24:28 +00:00
let voronoi = Delaunay . from ( this . cells . map (
( cell ) => [ cell . point . x , cell . point . y ] )
) . voronoi ( [
bounding _box . x , bounding _box . y ,
bounding _box . Right , bounding _box . Bottom
] ) ;
2019-05-29 20:06:00 +00:00
2019-06-10 22:24:28 +00:00
console . log ( voronoi ) ;
2019-05-29 20:08:01 +00:00
// TODO: Map the generated polygons back onto this.cells
2019-06-10 22:24:28 +00:00
let i = 0 ;
for ( let polygon of voronoi . cellPolygons ( ) ) {
let our _cell = this . cells [ i ] ;
our _cell . polygon = polygon . map ( ( point ) => new Vector2 ( ... point ) ) ;
i ++ ;
2019-06-09 22:51:41 +00:00
}
console . log ( this . cells ) ;
2019-05-29 20:06:00 +00:00
2019-06-11 00:07:11 +00:00
// TODO: Investigate GeoJSON. Maybe it could help us avoid the complexity of an SVGOverlay? It looks like we might be able to apply a custom colour to a GeoJSON polygon too: https://leafletjs.com/reference-1.5.0.html#geojson
2019-06-11 11:13:20 +00:00
let geojson = [ ] ;
2019-05-29 20:08:01 +00:00
// TODO: Render the SVG here
2019-06-10 22:24:28 +00:00
for ( let cell of this . cells ) {
2019-06-11 11:13:20 +00:00
if ( cell . polygon == null ) {
console . warn ( "Warning: Null cell polygon encountered." , cell ) ;
continue ;
2019-06-10 23:19:37 +00:00
}
2019-06-11 11:13:20 +00:00
geojson . push ( {
"type" : "Feature" ,
"geometry" : {
"type" : "Polygon" ,
"coordinates" : [ cell . polygon . map ( ( point ) => [ point . x , point . y ] ) ] ,
} ,
"properties" : {
// TODO: Replace this with an actual colour
"colour" : ` hsla( ${ ( Math . random ( ) * 360 ) . toFixed ( 2 ) } , 50%, 50%, 0.6) `
}
} ) ;
2019-06-10 22:24:28 +00:00
}
2019-06-11 11:13:20 +00:00
return geojson ;
2019-06-10 22:24:28 +00:00
}
add _to ( map ) {
2019-06-11 11:13:20 +00:00
this . layer = L . geoJSON ( this . render ( ) , {
style : ( feature ) => { return { color : feature . properties . colour } }
} ) ;
2019-06-10 22:24:28 +00:00
this . layer . addTo ( map ) ;
2019-05-29 20:08:01 +00:00
}
generate _overlay ( ) {
// TODO: Generate the Leaflet SVGOverlay here
2019-05-29 19:21:03 +00:00
}
}
2019-05-29 20:06:00 +00:00
2019-05-29 19:21:03 +00:00
export default VoronoiOverlay ;