1- import { geoCentroid as GeoCentroid , geoPath } from "d3" ;
1+ import { geoCentroid as GeoCentroid , geoPath , greatest , polygonArea , polygonContains } from "d3" ;
22import { memoize1 } from "../memoize.js" ;
33import { identity , valueof } from "../options.js" ;
44import { initializer } from "./basic.js" ;
5+ import polylabel from "polylabel" ;
56
67export function centroid ( { geometry = identity , ...options } = { } ) {
78 const getG = memoize1 ( ( data ) => valueof ( data , geometry ) ) ;
@@ -28,6 +29,55 @@ export function centroid({geometry = identity, ...options} = {}) {
2829 ) ;
2930}
3031
32+ export function poi ( { geometry = identity , ...options } = { } ) {
33+ const getG = memoize1 ( ( data ) => valueof ( data , geometry ) ) ;
34+ return initializer (
35+ { ...options , x : null , y : null , geometry : { transform : getG } } ,
36+ ( data , facets , channels , scales , dimensions , { projection} ) => {
37+ const G = getG ( data ) ;
38+ const n = G . length ;
39+ const X = new Float64Array ( n ) ;
40+ const Y = new Float64Array ( n ) ;
41+ let polygons , holes , ring ;
42+ const alpha = 2 ;
43+ const context = {
44+ arc ( ) { } ,
45+ moveTo ( x , y ) {
46+ ring = [ [ x , - alpha * y ] ] ;
47+ } ,
48+ lineTo ( x , y ) {
49+ ring . push ( [ x , - alpha * y ] ) ;
50+ } ,
51+ closePath ( ) {
52+ ring . push ( ring [ 0 ] ) ;
53+ if ( polygonArea ( ring ) > 0 ) polygons . push ( [ ring ] ) ;
54+ else holes . push ( ring ) ;
55+ }
56+ } ;
57+ const path = geoPath ( projection , context ) ;
58+ for ( let i = 0 ; i < n ; ++ i ) {
59+ polygons = [ ] ;
60+ holes = [ ] ;
61+ path ( G [ i ] ) ;
62+ for ( const h of holes ) polygons . find ( ( [ ring ] ) => polygonContains ( ring , h [ 0 ] ) ) ?. push ( h ) ;
63+ const a = greatest (
64+ polygons . map ( ( d ) => polylabel ( d ) ) ,
65+ ( d ) => d . distance
66+ ) ;
67+ [ X [ i ] , Y [ i ] ] = a ? [ a [ 0 ] , - a [ 1 ] / alpha ] : path . centroid ( G [ i ] ) ;
68+ }
69+ return {
70+ data,
71+ facets,
72+ channels : {
73+ x : { value : X , scale : projection == null ? "x" : null , source : null } ,
74+ y : { value : Y , scale : projection == null ? "y" : null , source : null }
75+ }
76+ } ;
77+ }
78+ ) ;
79+ }
80+
3181export function geoCentroid ( { geometry = identity , ...options } = { } ) {
3282 const getG = memoize1 ( ( data ) => valueof ( data , geometry ) ) ;
3383 const getC = memoize1 ( ( data ) => valueof ( getG ( data ) , GeoCentroid ) ) ;
0 commit comments