@@ -7,8 +7,9 @@ if (Queue.default) Queue = Queue.default; // temporary webpack fix
77module . exports = polylabel ;
88module . exports . default = polylabel ;
99
10- function polylabel ( polygon , precision , debug ) {
10+ function polylabel ( polygon , precision , debug , centroidWeight ) {
1111 precision = precision || 1.0 ;
12+ centroidWeight = centroidWeight || 0 ;
1213
1314 // find the bounding box of the outer ring
1415 var minX , minY , maxX , maxY ;
@@ -34,19 +35,26 @@ function polylabel(polygon, precision, debug) {
3435 // a priority queue of cells in order of their "potential" (max distance to polygon)
3536 var cellQueue = new Queue ( undefined , compareMax ) ;
3637
38+ var centroidCell = getCentroidCell ( polygon ) ;
39+
40+ // take centroid as the first best guess
41+ var bestCell = centroidCell ;
42+
3743 // cover polygon with initial cells
3844 for ( var x = minX ; x < maxX ; x += cellSize ) {
3945 for ( var y = minY ; y < maxY ; y += cellSize ) {
40- cellQueue . push ( new Cell ( x + h , y + h , h , polygon ) ) ;
46+ cellQueue . push ( new Cell ( x + h , y + h , h , polygon , centroidCell ) ) ;
4147 }
4248 }
4349
44- // take centroid as the first best guess
45- var bestCell = getCentroidCell ( polygon ) ;
50+ // the fitness function to be maximized
51+ function fitness ( cell ) {
52+ return cell . d - cell . distanceToCentroid * centroidWeight ;
53+ }
4654
4755 // special case for rectangular polygons
48- var bboxCell = new Cell ( minX + width / 2 , minY + height / 2 , 0 , polygon ) ;
49- if ( bboxCell . d > bestCell . d ) bestCell = bboxCell ;
56+ var bboxCell = new Cell ( minX + width / 2 , minY + height / 2 , 0 , polygon , centroidCell ) ;
57+ if ( fitness ( bboxCell ) > fitness ( bestCell ) ) bestCell = bboxCell ;
5058
5159 var numProbes = cellQueue . length ;
5260
@@ -55,7 +63,7 @@ function polylabel(polygon, precision, debug) {
5563 var cell = cellQueue . pop ( ) ;
5664
5765 // update the best cell if we found a better one
58- if ( cell . d > bestCell . d ) {
66+ if ( fitness ( cell ) > fitness ( bestCell ) ) {
5967 bestCell = cell ;
6068 if ( debug ) console . log ( 'found best %d after %d probes' , Math . round ( 1e4 * cell . d ) / 1e4 , numProbes ) ;
6169 }
@@ -65,10 +73,10 @@ function polylabel(polygon, precision, debug) {
6573
6674 // split the cell into four cells
6775 h = cell . h / 2 ;
68- cellQueue . push ( new Cell ( cell . x - h , cell . y - h , h , polygon ) ) ;
69- cellQueue . push ( new Cell ( cell . x + h , cell . y - h , h , polygon ) ) ;
70- cellQueue . push ( new Cell ( cell . x - h , cell . y + h , h , polygon ) ) ;
71- cellQueue . push ( new Cell ( cell . x + h , cell . y + h , h , polygon ) ) ;
76+ cellQueue . push ( new Cell ( cell . x - h , cell . y - h , h , polygon , centroidCell ) ) ;
77+ cellQueue . push ( new Cell ( cell . x + h , cell . y - h , h , polygon , centroidCell ) ) ;
78+ cellQueue . push ( new Cell ( cell . x - h , cell . y + h , h , polygon , centroidCell ) ) ;
79+ cellQueue . push ( new Cell ( cell . x + h , cell . y + h , h , polygon , centroidCell ) ) ;
7280 numProbes += 4 ;
7381 }
7482
@@ -86,14 +94,22 @@ function compareMax(a, b) {
8694 return b . max - a . max ;
8795}
8896
89- function Cell ( x , y , h , polygon ) {
97+ function Cell ( x , y , h , polygon , centroidCell ) {
9098 this . x = x ; // cell center x
9199 this . y = y ; // cell center y
92100 this . h = h ; // half the cell size
93101 this . d = pointToPolygonDist ( x , y , polygon ) ; // distance from cell center to polygon
102+ this . distanceToCentroid = centroidCell ? pointToPointDist ( this , centroidCell ) : 0 ;
94103 this . max = this . d + this . h * Math . SQRT2 ; // max distance to polygon within a cell
95104}
96105
106+ // distance between two cells
107+ function pointToPointDist ( cellA , cellB ) {
108+ var dx = cellB . x - cellA . x ;
109+ var dy = cellB . y - cellA . y ;
110+ return Math . sqrt ( dx * dx + dy * dy ) ;
111+ }
112+
97113// signed distance from point to polygon outline (negative if point is outside)
98114function pointToPolygonDist ( x , y , polygon ) {
99115 var inside = false ;
0 commit comments