@@ -20,6 +20,10 @@ import {
2020import { constant , isObject } from "./options.js" ;
2121import { warn } from "./warnings.js" ;
2222
23+ const pi = Math . PI ;
24+ const tau = 2 * pi ;
25+ const golden = 1.618 ;
26+
2327export function Projection (
2428 {
2529 projection,
@@ -57,8 +61,8 @@ export function Projection(
5761 if ( projection == null ) return ;
5862 }
5963
60- // For named projections, retrieve the corresponding projection initializer.
61- if ( typeof projection !== "function" ) projection = namedProjection ( projection ) ;
64+ // For named projections, retrieve the corresponding projection initializer and default aspect ratio .
65+ if ( typeof projection !== "function" ) ( { projection} = namedProjection ( projection ) ) ;
6266
6367 // Compute the frame dimensions and invoke the projection initializer.
6468 const { width, height, marginLeft, marginRight, marginTop, marginBottom} = dimensions ;
@@ -104,51 +108,40 @@ export function Projection(
104108 return { stream : ( s ) => projection . stream ( transform . stream ( clip ( s ) ) ) } ;
105109}
106110
107- export function hasProjection ( { projection} = { } ) {
108- if ( projection == null ) return false ;
109- if ( typeof projection . stream === "function" ) return true ; // d3 projection
110- if ( isObject ( projection ) ) ( { type : projection } = projection ) ;
111- if ( typeof projection !== "function" ) projection = namedProjection ( projection ) ;
112- return projection != null ;
113- }
114-
115- const pi = Math . PI ;
116- const tau = 2 * pi ;
117-
118111function namedProjection ( projection ) {
119112 switch ( `${ projection } ` . toLowerCase ( ) ) {
120113 case "albers-usa" :
121- return scaleProjection ( geoAlbersUsa , 0.7463 , 0.4673 ) ;
114+ return { projection : scaleProjection ( geoAlbersUsa , 0.7463 , 0.4673 ) , ratio : 610 / 975 } ;
122115 case "albers" :
123- return conicProjection ( geoAlbers , 0.7463 , 0.4673 ) ;
116+ return { projection : conicProjection ( geoAlbers , 0.7463 , 0.4673 ) , ratio : 610 / 975 } ;
124117 case "azimuthal-equal-area" :
125- return scaleProjection ( geoAzimuthalEqualArea , 4 , 4 ) ;
118+ return { projection : scaleProjection ( geoAzimuthalEqualArea , 4 , 4 ) , ratio : 1 } ;
126119 case "azimuthal-equidistant" :
127- return scaleProjection ( geoAzimuthalEquidistant , tau , tau ) ;
120+ return { projection : scaleProjection ( geoAzimuthalEquidistant , tau , tau ) , ratio : 1 } ;
128121 case "conic-conformal" :
129- return conicProjection ( geoConicConformal , tau , tau ) ;
122+ return { projection : conicProjection ( geoConicConformal , tau , tau ) } ;
130123 case "conic-equal-area" :
131- return conicProjection ( geoConicEqualArea , 6.1702 , 2.9781 ) ;
124+ return { projection : conicProjection ( geoConicEqualArea , 6.1702 , 2.9781 ) } ;
132125 case "conic-equidistant" :
133- return conicProjection ( geoConicEquidistant , 7.312 , 3.6282 ) ;
126+ return { projection : conicProjection ( geoConicEquidistant , 7.312 , 3.6282 ) } ;
134127 case "equal-earth" :
135- return scaleProjection ( geoEqualEarth , 5.4133 , 2.6347 ) ;
128+ return { projection : scaleProjection ( geoEqualEarth , 5.4133 , 2.6347 ) , ratio : 0.4867 } ;
136129 case "equirectangular" :
137- return scaleProjection ( geoEquirectangular , tau , pi ) ;
130+ return { projection : scaleProjection ( geoEquirectangular , tau , pi ) , ratio : 0.5 } ;
138131 case "gnomonic" :
139- return scaleProjection ( geoGnomonic , 3.4641 , 3.4641 ) ;
132+ return { projection : scaleProjection ( geoGnomonic , 3.4641 , 3.4641 ) } ;
140133 case "identity" :
141- return identity ;
134+ return { projection : identity } ;
142135 case "reflect-y" :
143- return reflectY ;
136+ return { projection : reflectY } ;
144137 case "mercator" :
145- return scaleProjection ( geoMercator , tau , tau ) ;
138+ return { projection : scaleProjection ( geoMercator , tau , tau ) , ratio : 1 } ;
146139 case "orthographic" :
147- return scaleProjection ( geoOrthographic , 2 , 2 ) ;
140+ return { projection : scaleProjection ( geoOrthographic , 2 , 2 ) , ratio : 1 } ;
148141 case "stereographic" :
149- return scaleProjection ( geoStereographic , 2 , 2 ) ;
142+ return { projection : scaleProjection ( geoStereographic , 2 , 2 ) } ;
150143 case "transverse-mercator" :
151- return scaleProjection ( geoTransverseMercator , tau , tau ) ;
144+ return { projection : scaleProjection ( geoTransverseMercator , tau , tau ) , ratio : 1 } ;
152145 default :
153146 throw new Error ( `unknown projection type: ${ projection } ` ) ;
154147 }
@@ -232,3 +225,15 @@ function applyProjection(cx, cy, values, projection) {
232225 stream . point ( x [ i ] , y [ i ] ) ;
233226 }
234227}
228+
229+ // When a projection is specified, try to determine a good value for the
230+ // projection’s height, if it is a named projection. When we don’t have a way to
231+ // know, the golden ratio is our best guess.
232+ export function projectionFitRatio ( { projection} = { } , geometry ) {
233+ if ( isObject ( projection ) ) projection = projection . type ;
234+ if ( typeof projection === "string" ) {
235+ const { ratio} = namedProjection ( projection ) ;
236+ if ( ratio ) return ratio ;
237+ }
238+ return geometry ? golden - 1 : 0 ;
239+ }
0 commit comments