Node-Red configuration
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

d3-geo.js 88KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167
  1. // https://d3js.org/d3-geo/ v3.1.1 Copyright 2010-2024 Mike Bostock, 2008-2012 Charles Karney
  2. (function (global, factory) {
  3. typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-array')) :
  4. typeof define === 'function' && define.amd ? define(['exports', 'd3-array'], factory) :
  5. (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.d3 = global.d3 || {}, global.d3));
  6. })(this, (function (exports, d3Array) { 'use strict';
  7. var epsilon = 1e-6;
  8. var epsilon2 = 1e-12;
  9. var pi = Math.PI;
  10. var halfPi = pi / 2;
  11. var quarterPi = pi / 4;
  12. var tau = pi * 2;
  13. var degrees = 180 / pi;
  14. var radians = pi / 180;
  15. var abs = Math.abs;
  16. var atan = Math.atan;
  17. var atan2 = Math.atan2;
  18. var cos = Math.cos;
  19. var ceil = Math.ceil;
  20. var exp = Math.exp;
  21. var hypot = Math.hypot;
  22. var log = Math.log;
  23. var pow = Math.pow;
  24. var sin = Math.sin;
  25. var sign = Math.sign || function(x) { return x > 0 ? 1 : x < 0 ? -1 : 0; };
  26. var sqrt = Math.sqrt;
  27. var tan = Math.tan;
  28. function acos(x) {
  29. return x > 1 ? 0 : x < -1 ? pi : Math.acos(x);
  30. }
  31. function asin(x) {
  32. return x > 1 ? halfPi : x < -1 ? -halfPi : Math.asin(x);
  33. }
  34. function haversin(x) {
  35. return (x = sin(x / 2)) * x;
  36. }
  37. function noop() {}
  38. function streamGeometry(geometry, stream) {
  39. if (geometry && streamGeometryType.hasOwnProperty(geometry.type)) {
  40. streamGeometryType[geometry.type](geometry, stream);
  41. }
  42. }
  43. var streamObjectType = {
  44. Feature: function(object, stream) {
  45. streamGeometry(object.geometry, stream);
  46. },
  47. FeatureCollection: function(object, stream) {
  48. var features = object.features, i = -1, n = features.length;
  49. while (++i < n) streamGeometry(features[i].geometry, stream);
  50. }
  51. };
  52. var streamGeometryType = {
  53. Sphere: function(object, stream) {
  54. stream.sphere();
  55. },
  56. Point: function(object, stream) {
  57. object = object.coordinates;
  58. stream.point(object[0], object[1], object[2]);
  59. },
  60. MultiPoint: function(object, stream) {
  61. var coordinates = object.coordinates, i = -1, n = coordinates.length;
  62. while (++i < n) object = coordinates[i], stream.point(object[0], object[1], object[2]);
  63. },
  64. LineString: function(object, stream) {
  65. streamLine(object.coordinates, stream, 0);
  66. },
  67. MultiLineString: function(object, stream) {
  68. var coordinates = object.coordinates, i = -1, n = coordinates.length;
  69. while (++i < n) streamLine(coordinates[i], stream, 0);
  70. },
  71. Polygon: function(object, stream) {
  72. streamPolygon(object.coordinates, stream);
  73. },
  74. MultiPolygon: function(object, stream) {
  75. var coordinates = object.coordinates, i = -1, n = coordinates.length;
  76. while (++i < n) streamPolygon(coordinates[i], stream);
  77. },
  78. GeometryCollection: function(object, stream) {
  79. var geometries = object.geometries, i = -1, n = geometries.length;
  80. while (++i < n) streamGeometry(geometries[i], stream);
  81. }
  82. };
  83. function streamLine(coordinates, stream, closed) {
  84. var i = -1, n = coordinates.length - closed, coordinate;
  85. stream.lineStart();
  86. while (++i < n) coordinate = coordinates[i], stream.point(coordinate[0], coordinate[1], coordinate[2]);
  87. stream.lineEnd();
  88. }
  89. function streamPolygon(coordinates, stream) {
  90. var i = -1, n = coordinates.length;
  91. stream.polygonStart();
  92. while (++i < n) streamLine(coordinates[i], stream, 1);
  93. stream.polygonEnd();
  94. }
  95. function geoStream(object, stream) {
  96. if (object && streamObjectType.hasOwnProperty(object.type)) {
  97. streamObjectType[object.type](object, stream);
  98. } else {
  99. streamGeometry(object, stream);
  100. }
  101. }
  102. var areaRingSum$1 = new d3Array.Adder();
  103. // hello?
  104. var areaSum$1 = new d3Array.Adder(),
  105. lambda00$2,
  106. phi00$2,
  107. lambda0$2,
  108. cosPhi0$1,
  109. sinPhi0$1;
  110. var areaStream$1 = {
  111. point: noop,
  112. lineStart: noop,
  113. lineEnd: noop,
  114. polygonStart: function() {
  115. areaRingSum$1 = new d3Array.Adder();
  116. areaStream$1.lineStart = areaRingStart$1;
  117. areaStream$1.lineEnd = areaRingEnd$1;
  118. },
  119. polygonEnd: function() {
  120. var areaRing = +areaRingSum$1;
  121. areaSum$1.add(areaRing < 0 ? tau + areaRing : areaRing);
  122. this.lineStart = this.lineEnd = this.point = noop;
  123. },
  124. sphere: function() {
  125. areaSum$1.add(tau);
  126. }
  127. };
  128. function areaRingStart$1() {
  129. areaStream$1.point = areaPointFirst$1;
  130. }
  131. function areaRingEnd$1() {
  132. areaPoint$1(lambda00$2, phi00$2);
  133. }
  134. function areaPointFirst$1(lambda, phi) {
  135. areaStream$1.point = areaPoint$1;
  136. lambda00$2 = lambda, phi00$2 = phi;
  137. lambda *= radians, phi *= radians;
  138. lambda0$2 = lambda, cosPhi0$1 = cos(phi = phi / 2 + quarterPi), sinPhi0$1 = sin(phi);
  139. }
  140. function areaPoint$1(lambda, phi) {
  141. lambda *= radians, phi *= radians;
  142. phi = phi / 2 + quarterPi; // half the angular distance from south pole
  143. // Spherical excess E for a spherical triangle with vertices: south pole,
  144. // previous point, current point. Uses a formula derived from Cagnoli’s
  145. // theorem. See Todhunter, Spherical Trig. (1871), Sec. 103, Eq. (2).
  146. var dLambda = lambda - lambda0$2,
  147. sdLambda = dLambda >= 0 ? 1 : -1,
  148. adLambda = sdLambda * dLambda,
  149. cosPhi = cos(phi),
  150. sinPhi = sin(phi),
  151. k = sinPhi0$1 * sinPhi,
  152. u = cosPhi0$1 * cosPhi + k * cos(adLambda),
  153. v = k * sdLambda * sin(adLambda);
  154. areaRingSum$1.add(atan2(v, u));
  155. // Advance the previous points.
  156. lambda0$2 = lambda, cosPhi0$1 = cosPhi, sinPhi0$1 = sinPhi;
  157. }
  158. function area(object) {
  159. areaSum$1 = new d3Array.Adder();
  160. geoStream(object, areaStream$1);
  161. return areaSum$1 * 2;
  162. }
  163. function spherical(cartesian) {
  164. return [atan2(cartesian[1], cartesian[0]), asin(cartesian[2])];
  165. }
  166. function cartesian(spherical) {
  167. var lambda = spherical[0], phi = spherical[1], cosPhi = cos(phi);
  168. return [cosPhi * cos(lambda), cosPhi * sin(lambda), sin(phi)];
  169. }
  170. function cartesianDot(a, b) {
  171. return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
  172. }
  173. function cartesianCross(a, b) {
  174. return [a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]];
  175. }
  176. // TODO return a
  177. function cartesianAddInPlace(a, b) {
  178. a[0] += b[0], a[1] += b[1], a[2] += b[2];
  179. }
  180. function cartesianScale(vector, k) {
  181. return [vector[0] * k, vector[1] * k, vector[2] * k];
  182. }
  183. // TODO return d
  184. function cartesianNormalizeInPlace(d) {
  185. var l = sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
  186. d[0] /= l, d[1] /= l, d[2] /= l;
  187. }
  188. var lambda0$1, phi0, lambda1, phi1, // bounds
  189. lambda2, // previous lambda-coordinate
  190. lambda00$1, phi00$1, // first point
  191. p0, // previous 3D point
  192. deltaSum,
  193. ranges,
  194. range;
  195. var boundsStream$1 = {
  196. point: boundsPoint$1,
  197. lineStart: boundsLineStart,
  198. lineEnd: boundsLineEnd,
  199. polygonStart: function() {
  200. boundsStream$1.point = boundsRingPoint;
  201. boundsStream$1.lineStart = boundsRingStart;
  202. boundsStream$1.lineEnd = boundsRingEnd;
  203. deltaSum = new d3Array.Adder();
  204. areaStream$1.polygonStart();
  205. },
  206. polygonEnd: function() {
  207. areaStream$1.polygonEnd();
  208. boundsStream$1.point = boundsPoint$1;
  209. boundsStream$1.lineStart = boundsLineStart;
  210. boundsStream$1.lineEnd = boundsLineEnd;
  211. if (areaRingSum$1 < 0) lambda0$1 = -(lambda1 = 180), phi0 = -(phi1 = 90);
  212. else if (deltaSum > epsilon) phi1 = 90;
  213. else if (deltaSum < -epsilon) phi0 = -90;
  214. range[0] = lambda0$1, range[1] = lambda1;
  215. },
  216. sphere: function() {
  217. lambda0$1 = -(lambda1 = 180), phi0 = -(phi1 = 90);
  218. }
  219. };
  220. function boundsPoint$1(lambda, phi) {
  221. ranges.push(range = [lambda0$1 = lambda, lambda1 = lambda]);
  222. if (phi < phi0) phi0 = phi;
  223. if (phi > phi1) phi1 = phi;
  224. }
  225. function linePoint(lambda, phi) {
  226. var p = cartesian([lambda * radians, phi * radians]);
  227. if (p0) {
  228. var normal = cartesianCross(p0, p),
  229. equatorial = [normal[1], -normal[0], 0],
  230. inflection = cartesianCross(equatorial, normal);
  231. cartesianNormalizeInPlace(inflection);
  232. inflection = spherical(inflection);
  233. var delta = lambda - lambda2,
  234. sign = delta > 0 ? 1 : -1,
  235. lambdai = inflection[0] * degrees * sign,
  236. phii,
  237. antimeridian = abs(delta) > 180;
  238. if (antimeridian ^ (sign * lambda2 < lambdai && lambdai < sign * lambda)) {
  239. phii = inflection[1] * degrees;
  240. if (phii > phi1) phi1 = phii;
  241. } else if (lambdai = (lambdai + 360) % 360 - 180, antimeridian ^ (sign * lambda2 < lambdai && lambdai < sign * lambda)) {
  242. phii = -inflection[1] * degrees;
  243. if (phii < phi0) phi0 = phii;
  244. } else {
  245. if (phi < phi0) phi0 = phi;
  246. if (phi > phi1) phi1 = phi;
  247. }
  248. if (antimeridian) {
  249. if (lambda < lambda2) {
  250. if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) lambda1 = lambda;
  251. } else {
  252. if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) lambda0$1 = lambda;
  253. }
  254. } else {
  255. if (lambda1 >= lambda0$1) {
  256. if (lambda < lambda0$1) lambda0$1 = lambda;
  257. if (lambda > lambda1) lambda1 = lambda;
  258. } else {
  259. if (lambda > lambda2) {
  260. if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) lambda1 = lambda;
  261. } else {
  262. if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) lambda0$1 = lambda;
  263. }
  264. }
  265. }
  266. } else {
  267. ranges.push(range = [lambda0$1 = lambda, lambda1 = lambda]);
  268. }
  269. if (phi < phi0) phi0 = phi;
  270. if (phi > phi1) phi1 = phi;
  271. p0 = p, lambda2 = lambda;
  272. }
  273. function boundsLineStart() {
  274. boundsStream$1.point = linePoint;
  275. }
  276. function boundsLineEnd() {
  277. range[0] = lambda0$1, range[1] = lambda1;
  278. boundsStream$1.point = boundsPoint$1;
  279. p0 = null;
  280. }
  281. function boundsRingPoint(lambda, phi) {
  282. if (p0) {
  283. var delta = lambda - lambda2;
  284. deltaSum.add(abs(delta) > 180 ? delta + (delta > 0 ? 360 : -360) : delta);
  285. } else {
  286. lambda00$1 = lambda, phi00$1 = phi;
  287. }
  288. areaStream$1.point(lambda, phi);
  289. linePoint(lambda, phi);
  290. }
  291. function boundsRingStart() {
  292. areaStream$1.lineStart();
  293. }
  294. function boundsRingEnd() {
  295. boundsRingPoint(lambda00$1, phi00$1);
  296. areaStream$1.lineEnd();
  297. if (abs(deltaSum) > epsilon) lambda0$1 = -(lambda1 = 180);
  298. range[0] = lambda0$1, range[1] = lambda1;
  299. p0 = null;
  300. }
  301. // Finds the left-right distance between two longitudes.
  302. // This is almost the same as (lambda1 - lambda0 + 360°) % 360°, except that we want
  303. // the distance between ±180° to be 360°.
  304. function angle(lambda0, lambda1) {
  305. return (lambda1 -= lambda0) < 0 ? lambda1 + 360 : lambda1;
  306. }
  307. function rangeCompare(a, b) {
  308. return a[0] - b[0];
  309. }
  310. function rangeContains(range, x) {
  311. return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x;
  312. }
  313. function bounds(feature) {
  314. var i, n, a, b, merged, deltaMax, delta;
  315. phi1 = lambda1 = -(lambda0$1 = phi0 = Infinity);
  316. ranges = [];
  317. geoStream(feature, boundsStream$1);
  318. // First, sort ranges by their minimum longitudes.
  319. if (n = ranges.length) {
  320. ranges.sort(rangeCompare);
  321. // Then, merge any ranges that overlap.
  322. for (i = 1, a = ranges[0], merged = [a]; i < n; ++i) {
  323. b = ranges[i];
  324. if (rangeContains(a, b[0]) || rangeContains(a, b[1])) {
  325. if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1];
  326. if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0];
  327. } else {
  328. merged.push(a = b);
  329. }
  330. }
  331. // Finally, find the largest gap between the merged ranges.
  332. // The final bounding box will be the inverse of this gap.
  333. for (deltaMax = -Infinity, n = merged.length - 1, i = 0, a = merged[n]; i <= n; a = b, ++i) {
  334. b = merged[i];
  335. if ((delta = angle(a[1], b[0])) > deltaMax) deltaMax = delta, lambda0$1 = b[0], lambda1 = a[1];
  336. }
  337. }
  338. ranges = range = null;
  339. return lambda0$1 === Infinity || phi0 === Infinity
  340. ? [[NaN, NaN], [NaN, NaN]]
  341. : [[lambda0$1, phi0], [lambda1, phi1]];
  342. }
  343. var W0, W1,
  344. X0$1, Y0$1, Z0$1,
  345. X1$1, Y1$1, Z1$1,
  346. X2$1, Y2$1, Z2$1,
  347. lambda00, phi00, // first point
  348. x0$4, y0$4, z0; // previous point
  349. var centroidStream$1 = {
  350. sphere: noop,
  351. point: centroidPoint$1,
  352. lineStart: centroidLineStart$1,
  353. lineEnd: centroidLineEnd$1,
  354. polygonStart: function() {
  355. centroidStream$1.lineStart = centroidRingStart$1;
  356. centroidStream$1.lineEnd = centroidRingEnd$1;
  357. },
  358. polygonEnd: function() {
  359. centroidStream$1.lineStart = centroidLineStart$1;
  360. centroidStream$1.lineEnd = centroidLineEnd$1;
  361. }
  362. };
  363. // Arithmetic mean of Cartesian vectors.
  364. function centroidPoint$1(lambda, phi) {
  365. lambda *= radians, phi *= radians;
  366. var cosPhi = cos(phi);
  367. centroidPointCartesian(cosPhi * cos(lambda), cosPhi * sin(lambda), sin(phi));
  368. }
  369. function centroidPointCartesian(x, y, z) {
  370. ++W0;
  371. X0$1 += (x - X0$1) / W0;
  372. Y0$1 += (y - Y0$1) / W0;
  373. Z0$1 += (z - Z0$1) / W0;
  374. }
  375. function centroidLineStart$1() {
  376. centroidStream$1.point = centroidLinePointFirst;
  377. }
  378. function centroidLinePointFirst(lambda, phi) {
  379. lambda *= radians, phi *= radians;
  380. var cosPhi = cos(phi);
  381. x0$4 = cosPhi * cos(lambda);
  382. y0$4 = cosPhi * sin(lambda);
  383. z0 = sin(phi);
  384. centroidStream$1.point = centroidLinePoint;
  385. centroidPointCartesian(x0$4, y0$4, z0);
  386. }
  387. function centroidLinePoint(lambda, phi) {
  388. lambda *= radians, phi *= radians;
  389. var cosPhi = cos(phi),
  390. x = cosPhi * cos(lambda),
  391. y = cosPhi * sin(lambda),
  392. z = sin(phi),
  393. w = atan2(sqrt((w = y0$4 * z - z0 * y) * w + (w = z0 * x - x0$4 * z) * w + (w = x0$4 * y - y0$4 * x) * w), x0$4 * x + y0$4 * y + z0 * z);
  394. W1 += w;
  395. X1$1 += w * (x0$4 + (x0$4 = x));
  396. Y1$1 += w * (y0$4 + (y0$4 = y));
  397. Z1$1 += w * (z0 + (z0 = z));
  398. centroidPointCartesian(x0$4, y0$4, z0);
  399. }
  400. function centroidLineEnd$1() {
  401. centroidStream$1.point = centroidPoint$1;
  402. }
  403. // See J. E. Brock, The Inertia Tensor for a Spherical Triangle,
  404. // J. Applied Mechanics 42, 239 (1975).
  405. function centroidRingStart$1() {
  406. centroidStream$1.point = centroidRingPointFirst;
  407. }
  408. function centroidRingEnd$1() {
  409. centroidRingPoint(lambda00, phi00);
  410. centroidStream$1.point = centroidPoint$1;
  411. }
  412. function centroidRingPointFirst(lambda, phi) {
  413. lambda00 = lambda, phi00 = phi;
  414. lambda *= radians, phi *= radians;
  415. centroidStream$1.point = centroidRingPoint;
  416. var cosPhi = cos(phi);
  417. x0$4 = cosPhi * cos(lambda);
  418. y0$4 = cosPhi * sin(lambda);
  419. z0 = sin(phi);
  420. centroidPointCartesian(x0$4, y0$4, z0);
  421. }
  422. function centroidRingPoint(lambda, phi) {
  423. lambda *= radians, phi *= radians;
  424. var cosPhi = cos(phi),
  425. x = cosPhi * cos(lambda),
  426. y = cosPhi * sin(lambda),
  427. z = sin(phi),
  428. cx = y0$4 * z - z0 * y,
  429. cy = z0 * x - x0$4 * z,
  430. cz = x0$4 * y - y0$4 * x,
  431. m = hypot(cx, cy, cz),
  432. w = asin(m), // line weight = angle
  433. v = m && -w / m; // area weight multiplier
  434. X2$1.add(v * cx);
  435. Y2$1.add(v * cy);
  436. Z2$1.add(v * cz);
  437. W1 += w;
  438. X1$1 += w * (x0$4 + (x0$4 = x));
  439. Y1$1 += w * (y0$4 + (y0$4 = y));
  440. Z1$1 += w * (z0 + (z0 = z));
  441. centroidPointCartesian(x0$4, y0$4, z0);
  442. }
  443. function centroid(object) {
  444. W0 = W1 =
  445. X0$1 = Y0$1 = Z0$1 =
  446. X1$1 = Y1$1 = Z1$1 = 0;
  447. X2$1 = new d3Array.Adder();
  448. Y2$1 = new d3Array.Adder();
  449. Z2$1 = new d3Array.Adder();
  450. geoStream(object, centroidStream$1);
  451. var x = +X2$1,
  452. y = +Y2$1,
  453. z = +Z2$1,
  454. m = hypot(x, y, z);
  455. // If the area-weighted ccentroid is undefined, fall back to length-weighted ccentroid.
  456. if (m < epsilon2) {
  457. x = X1$1, y = Y1$1, z = Z1$1;
  458. // If the feature has zero length, fall back to arithmetic mean of point vectors.
  459. if (W1 < epsilon) x = X0$1, y = Y0$1, z = Z0$1;
  460. m = hypot(x, y, z);
  461. // If the feature still has an undefined ccentroid, then return.
  462. if (m < epsilon2) return [NaN, NaN];
  463. }
  464. return [atan2(y, x) * degrees, asin(z / m) * degrees];
  465. }
  466. function constant(x) {
  467. return function() {
  468. return x;
  469. };
  470. }
  471. function compose(a, b) {
  472. function compose(x, y) {
  473. return x = a(x, y), b(x[0], x[1]);
  474. }
  475. if (a.invert && b.invert) compose.invert = function(x, y) {
  476. return x = b.invert(x, y), x && a.invert(x[0], x[1]);
  477. };
  478. return compose;
  479. }
  480. function rotationIdentity(lambda, phi) {
  481. if (abs(lambda) > pi) lambda -= Math.round(lambda / tau) * tau;
  482. return [lambda, phi];
  483. }
  484. rotationIdentity.invert = rotationIdentity;
  485. function rotateRadians(deltaLambda, deltaPhi, deltaGamma) {
  486. return (deltaLambda %= tau) ? (deltaPhi || deltaGamma ? compose(rotationLambda(deltaLambda), rotationPhiGamma(deltaPhi, deltaGamma))
  487. : rotationLambda(deltaLambda))
  488. : (deltaPhi || deltaGamma ? rotationPhiGamma(deltaPhi, deltaGamma)
  489. : rotationIdentity);
  490. }
  491. function forwardRotationLambda(deltaLambda) {
  492. return function(lambda, phi) {
  493. lambda += deltaLambda;
  494. if (abs(lambda) > pi) lambda -= Math.round(lambda / tau) * tau;
  495. return [lambda, phi];
  496. };
  497. }
  498. function rotationLambda(deltaLambda) {
  499. var rotation = forwardRotationLambda(deltaLambda);
  500. rotation.invert = forwardRotationLambda(-deltaLambda);
  501. return rotation;
  502. }
  503. function rotationPhiGamma(deltaPhi, deltaGamma) {
  504. var cosDeltaPhi = cos(deltaPhi),
  505. sinDeltaPhi = sin(deltaPhi),
  506. cosDeltaGamma = cos(deltaGamma),
  507. sinDeltaGamma = sin(deltaGamma);
  508. function rotation(lambda, phi) {
  509. var cosPhi = cos(phi),
  510. x = cos(lambda) * cosPhi,
  511. y = sin(lambda) * cosPhi,
  512. z = sin(phi),
  513. k = z * cosDeltaPhi + x * sinDeltaPhi;
  514. return [
  515. atan2(y * cosDeltaGamma - k * sinDeltaGamma, x * cosDeltaPhi - z * sinDeltaPhi),
  516. asin(k * cosDeltaGamma + y * sinDeltaGamma)
  517. ];
  518. }
  519. rotation.invert = function(lambda, phi) {
  520. var cosPhi = cos(phi),
  521. x = cos(lambda) * cosPhi,
  522. y = sin(lambda) * cosPhi,
  523. z = sin(phi),
  524. k = z * cosDeltaGamma - y * sinDeltaGamma;
  525. return [
  526. atan2(y * cosDeltaGamma + z * sinDeltaGamma, x * cosDeltaPhi + k * sinDeltaPhi),
  527. asin(k * cosDeltaPhi - x * sinDeltaPhi)
  528. ];
  529. };
  530. return rotation;
  531. }
  532. function rotation(rotate) {
  533. rotate = rotateRadians(rotate[0] * radians, rotate[1] * radians, rotate.length > 2 ? rotate[2] * radians : 0);
  534. function forward(coordinates) {
  535. coordinates = rotate(coordinates[0] * radians, coordinates[1] * radians);
  536. return coordinates[0] *= degrees, coordinates[1] *= degrees, coordinates;
  537. }
  538. forward.invert = function(coordinates) {
  539. coordinates = rotate.invert(coordinates[0] * radians, coordinates[1] * radians);
  540. return coordinates[0] *= degrees, coordinates[1] *= degrees, coordinates;
  541. };
  542. return forward;
  543. }
  544. // Generates a circle centered at [0°, 0°], with a given radius and precision.
  545. function circleStream(stream, radius, delta, direction, t0, t1) {
  546. if (!delta) return;
  547. var cosRadius = cos(radius),
  548. sinRadius = sin(radius),
  549. step = direction * delta;
  550. if (t0 == null) {
  551. t0 = radius + direction * tau;
  552. t1 = radius - step / 2;
  553. } else {
  554. t0 = circleRadius(cosRadius, t0);
  555. t1 = circleRadius(cosRadius, t1);
  556. if (direction > 0 ? t0 < t1 : t0 > t1) t0 += direction * tau;
  557. }
  558. for (var point, t = t0; direction > 0 ? t > t1 : t < t1; t -= step) {
  559. point = spherical([cosRadius, -sinRadius * cos(t), -sinRadius * sin(t)]);
  560. stream.point(point[0], point[1]);
  561. }
  562. }
  563. // Returns the signed angle of a cartesian point relative to [cosRadius, 0, 0].
  564. function circleRadius(cosRadius, point) {
  565. point = cartesian(point), point[0] -= cosRadius;
  566. cartesianNormalizeInPlace(point);
  567. var radius = acos(-point[1]);
  568. return ((-point[2] < 0 ? -radius : radius) + tau - epsilon) % tau;
  569. }
  570. function circle() {
  571. var center = constant([0, 0]),
  572. radius = constant(90),
  573. precision = constant(2),
  574. ring,
  575. rotate,
  576. stream = {point: point};
  577. function point(x, y) {
  578. ring.push(x = rotate(x, y));
  579. x[0] *= degrees, x[1] *= degrees;
  580. }
  581. function circle() {
  582. var c = center.apply(this, arguments),
  583. r = radius.apply(this, arguments) * radians,
  584. p = precision.apply(this, arguments) * radians;
  585. ring = [];
  586. rotate = rotateRadians(-c[0] * radians, -c[1] * radians, 0).invert;
  587. circleStream(stream, r, p, 1);
  588. c = {type: "Polygon", coordinates: [ring]};
  589. ring = rotate = null;
  590. return c;
  591. }
  592. circle.center = function(_) {
  593. return arguments.length ? (center = typeof _ === "function" ? _ : constant([+_[0], +_[1]]), circle) : center;
  594. };
  595. circle.radius = function(_) {
  596. return arguments.length ? (radius = typeof _ === "function" ? _ : constant(+_), circle) : radius;
  597. };
  598. circle.precision = function(_) {
  599. return arguments.length ? (precision = typeof _ === "function" ? _ : constant(+_), circle) : precision;
  600. };
  601. return circle;
  602. }
  603. function clipBuffer() {
  604. var lines = [],
  605. line;
  606. return {
  607. point: function(x, y, m) {
  608. line.push([x, y, m]);
  609. },
  610. lineStart: function() {
  611. lines.push(line = []);
  612. },
  613. lineEnd: noop,
  614. rejoin: function() {
  615. if (lines.length > 1) lines.push(lines.pop().concat(lines.shift()));
  616. },
  617. result: function() {
  618. var result = lines;
  619. lines = [];
  620. line = null;
  621. return result;
  622. }
  623. };
  624. }
  625. function pointEqual(a, b) {
  626. return abs(a[0] - b[0]) < epsilon && abs(a[1] - b[1]) < epsilon;
  627. }
  628. function Intersection(point, points, other, entry) {
  629. this.x = point;
  630. this.z = points;
  631. this.o = other; // another intersection
  632. this.e = entry; // is an entry?
  633. this.v = false; // visited
  634. this.n = this.p = null; // next & previous
  635. }
  636. // A generalized polygon clipping algorithm: given a polygon that has been cut
  637. // into its visible line segments, and rejoins the segments by interpolating
  638. // along the clip edge.
  639. function clipRejoin(segments, compareIntersection, startInside, interpolate, stream) {
  640. var subject = [],
  641. clip = [],
  642. i,
  643. n;
  644. segments.forEach(function(segment) {
  645. if ((n = segment.length - 1) <= 0) return;
  646. var n, p0 = segment[0], p1 = segment[n], x;
  647. if (pointEqual(p0, p1)) {
  648. if (!p0[2] && !p1[2]) {
  649. stream.lineStart();
  650. for (i = 0; i < n; ++i) stream.point((p0 = segment[i])[0], p0[1]);
  651. stream.lineEnd();
  652. return;
  653. }
  654. // handle degenerate cases by moving the point
  655. p1[0] += 2 * epsilon;
  656. }
  657. subject.push(x = new Intersection(p0, segment, null, true));
  658. clip.push(x.o = new Intersection(p0, null, x, false));
  659. subject.push(x = new Intersection(p1, segment, null, false));
  660. clip.push(x.o = new Intersection(p1, null, x, true));
  661. });
  662. if (!subject.length) return;
  663. clip.sort(compareIntersection);
  664. link(subject);
  665. link(clip);
  666. for (i = 0, n = clip.length; i < n; ++i) {
  667. clip[i].e = startInside = !startInside;
  668. }
  669. var start = subject[0],
  670. points,
  671. point;
  672. while (1) {
  673. // Find first unvisited intersection.
  674. var current = start,
  675. isSubject = true;
  676. while (current.v) if ((current = current.n) === start) return;
  677. points = current.z;
  678. stream.lineStart();
  679. do {
  680. current.v = current.o.v = true;
  681. if (current.e) {
  682. if (isSubject) {
  683. for (i = 0, n = points.length; i < n; ++i) stream.point((point = points[i])[0], point[1]);
  684. } else {
  685. interpolate(current.x, current.n.x, 1, stream);
  686. }
  687. current = current.n;
  688. } else {
  689. if (isSubject) {
  690. points = current.p.z;
  691. for (i = points.length - 1; i >= 0; --i) stream.point((point = points[i])[0], point[1]);
  692. } else {
  693. interpolate(current.x, current.p.x, -1, stream);
  694. }
  695. current = current.p;
  696. }
  697. current = current.o;
  698. points = current.z;
  699. isSubject = !isSubject;
  700. } while (!current.v);
  701. stream.lineEnd();
  702. }
  703. }
  704. function link(array) {
  705. if (!(n = array.length)) return;
  706. var n,
  707. i = 0,
  708. a = array[0],
  709. b;
  710. while (++i < n) {
  711. a.n = b = array[i];
  712. b.p = a;
  713. a = b;
  714. }
  715. a.n = b = array[0];
  716. b.p = a;
  717. }
  718. function longitude(point) {
  719. return abs(point[0]) <= pi ? point[0] : sign(point[0]) * ((abs(point[0]) + pi) % tau - pi);
  720. }
  721. function polygonContains(polygon, point) {
  722. var lambda = longitude(point),
  723. phi = point[1],
  724. sinPhi = sin(phi),
  725. normal = [sin(lambda), -cos(lambda), 0],
  726. angle = 0,
  727. winding = 0;
  728. var sum = new d3Array.Adder();
  729. if (sinPhi === 1) phi = halfPi + epsilon;
  730. else if (sinPhi === -1) phi = -halfPi - epsilon;
  731. for (var i = 0, n = polygon.length; i < n; ++i) {
  732. if (!(m = (ring = polygon[i]).length)) continue;
  733. var ring,
  734. m,
  735. point0 = ring[m - 1],
  736. lambda0 = longitude(point0),
  737. phi0 = point0[1] / 2 + quarterPi,
  738. sinPhi0 = sin(phi0),
  739. cosPhi0 = cos(phi0);
  740. for (var j = 0; j < m; ++j, lambda0 = lambda1, sinPhi0 = sinPhi1, cosPhi0 = cosPhi1, point0 = point1) {
  741. var point1 = ring[j],
  742. lambda1 = longitude(point1),
  743. phi1 = point1[1] / 2 + quarterPi,
  744. sinPhi1 = sin(phi1),
  745. cosPhi1 = cos(phi1),
  746. delta = lambda1 - lambda0,
  747. sign = delta >= 0 ? 1 : -1,
  748. absDelta = sign * delta,
  749. antimeridian = absDelta > pi,
  750. k = sinPhi0 * sinPhi1;
  751. sum.add(atan2(k * sign * sin(absDelta), cosPhi0 * cosPhi1 + k * cos(absDelta)));
  752. angle += antimeridian ? delta + sign * tau : delta;
  753. // Are the longitudes either side of the point’s meridian (lambda),
  754. // and are the latitudes smaller than the parallel (phi)?
  755. if (antimeridian ^ lambda0 >= lambda ^ lambda1 >= lambda) {
  756. var arc = cartesianCross(cartesian(point0), cartesian(point1));
  757. cartesianNormalizeInPlace(arc);
  758. var intersection = cartesianCross(normal, arc);
  759. cartesianNormalizeInPlace(intersection);
  760. var phiArc = (antimeridian ^ delta >= 0 ? -1 : 1) * asin(intersection[2]);
  761. if (phi > phiArc || phi === phiArc && (arc[0] || arc[1])) {
  762. winding += antimeridian ^ delta >= 0 ? 1 : -1;
  763. }
  764. }
  765. }
  766. }
  767. // First, determine whether the South pole is inside or outside:
  768. //
  769. // It is inside if:
  770. // * the polygon winds around it in a clockwise direction.
  771. // * the polygon does not (cumulatively) wind around it, but has a negative
  772. // (counter-clockwise) area.
  773. //
  774. // Second, count the (signed) number of times a segment crosses a lambda
  775. // from the point to the South pole. If it is zero, then the point is the
  776. // same side as the South pole.
  777. return (angle < -epsilon || angle < epsilon && sum < -epsilon2) ^ (winding & 1);
  778. }
  779. function clip(pointVisible, clipLine, interpolate, start) {
  780. return function(sink) {
  781. var line = clipLine(sink),
  782. ringBuffer = clipBuffer(),
  783. ringSink = clipLine(ringBuffer),
  784. polygonStarted = false,
  785. polygon,
  786. segments,
  787. ring;
  788. var clip = {
  789. point: point,
  790. lineStart: lineStart,
  791. lineEnd: lineEnd,
  792. polygonStart: function() {
  793. clip.point = pointRing;
  794. clip.lineStart = ringStart;
  795. clip.lineEnd = ringEnd;
  796. segments = [];
  797. polygon = [];
  798. },
  799. polygonEnd: function() {
  800. clip.point = point;
  801. clip.lineStart = lineStart;
  802. clip.lineEnd = lineEnd;
  803. segments = d3Array.merge(segments);
  804. var startInside = polygonContains(polygon, start);
  805. if (segments.length) {
  806. if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
  807. clipRejoin(segments, compareIntersection, startInside, interpolate, sink);
  808. } else if (startInside) {
  809. if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
  810. sink.lineStart();
  811. interpolate(null, null, 1, sink);
  812. sink.lineEnd();
  813. }
  814. if (polygonStarted) sink.polygonEnd(), polygonStarted = false;
  815. segments = polygon = null;
  816. },
  817. sphere: function() {
  818. sink.polygonStart();
  819. sink.lineStart();
  820. interpolate(null, null, 1, sink);
  821. sink.lineEnd();
  822. sink.polygonEnd();
  823. }
  824. };
  825. function point(lambda, phi) {
  826. if (pointVisible(lambda, phi)) sink.point(lambda, phi);
  827. }
  828. function pointLine(lambda, phi) {
  829. line.point(lambda, phi);
  830. }
  831. function lineStart() {
  832. clip.point = pointLine;
  833. line.lineStart();
  834. }
  835. function lineEnd() {
  836. clip.point = point;
  837. line.lineEnd();
  838. }
  839. function pointRing(lambda, phi) {
  840. ring.push([lambda, phi]);
  841. ringSink.point(lambda, phi);
  842. }
  843. function ringStart() {
  844. ringSink.lineStart();
  845. ring = [];
  846. }
  847. function ringEnd() {
  848. pointRing(ring[0][0], ring[0][1]);
  849. ringSink.lineEnd();
  850. var clean = ringSink.clean(),
  851. ringSegments = ringBuffer.result(),
  852. i, n = ringSegments.length, m,
  853. segment,
  854. point;
  855. ring.pop();
  856. polygon.push(ring);
  857. ring = null;
  858. if (!n) return;
  859. // No intersections.
  860. if (clean & 1) {
  861. segment = ringSegments[0];
  862. if ((m = segment.length - 1) > 0) {
  863. if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
  864. sink.lineStart();
  865. for (i = 0; i < m; ++i) sink.point((point = segment[i])[0], point[1]);
  866. sink.lineEnd();
  867. }
  868. return;
  869. }
  870. // Rejoin connected segments.
  871. // TODO reuse ringBuffer.rejoin()?
  872. if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));
  873. segments.push(ringSegments.filter(validSegment));
  874. }
  875. return clip;
  876. };
  877. }
  878. function validSegment(segment) {
  879. return segment.length > 1;
  880. }
  881. // Intersections are sorted along the clip edge. For both antimeridian cutting
  882. // and circle clipping, the same comparison is used.
  883. function compareIntersection(a, b) {
  884. return ((a = a.x)[0] < 0 ? a[1] - halfPi - epsilon : halfPi - a[1])
  885. - ((b = b.x)[0] < 0 ? b[1] - halfPi - epsilon : halfPi - b[1]);
  886. }
  887. var clipAntimeridian = clip(
  888. function() { return true; },
  889. clipAntimeridianLine,
  890. clipAntimeridianInterpolate,
  891. [-pi, -halfPi]
  892. );
  893. // Takes a line and cuts into visible segments. Return values: 0 - there were
  894. // intersections or the line was empty; 1 - no intersections; 2 - there were
  895. // intersections, and the first and last segments should be rejoined.
  896. function clipAntimeridianLine(stream) {
  897. var lambda0 = NaN,
  898. phi0 = NaN,
  899. sign0 = NaN,
  900. clean; // no intersections
  901. return {
  902. lineStart: function() {
  903. stream.lineStart();
  904. clean = 1;
  905. },
  906. point: function(lambda1, phi1) {
  907. var sign1 = lambda1 > 0 ? pi : -pi,
  908. delta = abs(lambda1 - lambda0);
  909. if (abs(delta - pi) < epsilon) { // line crosses a pole
  910. stream.point(lambda0, phi0 = (phi0 + phi1) / 2 > 0 ? halfPi : -halfPi);
  911. stream.point(sign0, phi0);
  912. stream.lineEnd();
  913. stream.lineStart();
  914. stream.point(sign1, phi0);
  915. stream.point(lambda1, phi0);
  916. clean = 0;
  917. } else if (sign0 !== sign1 && delta >= pi) { // line crosses antimeridian
  918. if (abs(lambda0 - sign0) < epsilon) lambda0 -= sign0 * epsilon; // handle degeneracies
  919. if (abs(lambda1 - sign1) < epsilon) lambda1 -= sign1 * epsilon;
  920. phi0 = clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1);
  921. stream.point(sign0, phi0);
  922. stream.lineEnd();
  923. stream.lineStart();
  924. stream.point(sign1, phi0);
  925. clean = 0;
  926. }
  927. stream.point(lambda0 = lambda1, phi0 = phi1);
  928. sign0 = sign1;
  929. },
  930. lineEnd: function() {
  931. stream.lineEnd();
  932. lambda0 = phi0 = NaN;
  933. },
  934. clean: function() {
  935. return 2 - clean; // if intersections, rejoin first and last segments
  936. }
  937. };
  938. }
  939. function clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1) {
  940. var cosPhi0,
  941. cosPhi1,
  942. sinLambda0Lambda1 = sin(lambda0 - lambda1);
  943. return abs(sinLambda0Lambda1) > epsilon
  944. ? atan((sin(phi0) * (cosPhi1 = cos(phi1)) * sin(lambda1)
  945. - sin(phi1) * (cosPhi0 = cos(phi0)) * sin(lambda0))
  946. / (cosPhi0 * cosPhi1 * sinLambda0Lambda1))
  947. : (phi0 + phi1) / 2;
  948. }
  949. function clipAntimeridianInterpolate(from, to, direction, stream) {
  950. var phi;
  951. if (from == null) {
  952. phi = direction * halfPi;
  953. stream.point(-pi, phi);
  954. stream.point(0, phi);
  955. stream.point(pi, phi);
  956. stream.point(pi, 0);
  957. stream.point(pi, -phi);
  958. stream.point(0, -phi);
  959. stream.point(-pi, -phi);
  960. stream.point(-pi, 0);
  961. stream.point(-pi, phi);
  962. } else if (abs(from[0] - to[0]) > epsilon) {
  963. var lambda = from[0] < to[0] ? pi : -pi;
  964. phi = direction * lambda / 2;
  965. stream.point(-lambda, phi);
  966. stream.point(0, phi);
  967. stream.point(lambda, phi);
  968. } else {
  969. stream.point(to[0], to[1]);
  970. }
  971. }
  972. function clipCircle(radius) {
  973. var cr = cos(radius),
  974. delta = 2 * radians,
  975. smallRadius = cr > 0,
  976. notHemisphere = abs(cr) > epsilon; // TODO optimise for this common case
  977. function interpolate(from, to, direction, stream) {
  978. circleStream(stream, radius, delta, direction, from, to);
  979. }
  980. function visible(lambda, phi) {
  981. return cos(lambda) * cos(phi) > cr;
  982. }
  983. // Takes a line and cuts into visible segments. Return values used for polygon
  984. // clipping: 0 - there were intersections or the line was empty; 1 - no
  985. // intersections 2 - there were intersections, and the first and last segments
  986. // should be rejoined.
  987. function clipLine(stream) {
  988. var point0, // previous point
  989. c0, // code for previous point
  990. v0, // visibility of previous point
  991. v00, // visibility of first point
  992. clean; // no intersections
  993. return {
  994. lineStart: function() {
  995. v00 = v0 = false;
  996. clean = 1;
  997. },
  998. point: function(lambda, phi) {
  999. var point1 = [lambda, phi],
  1000. point2,
  1001. v = visible(lambda, phi),
  1002. c = smallRadius
  1003. ? v ? 0 : code(lambda, phi)
  1004. : v ? code(lambda + (lambda < 0 ? pi : -pi), phi) : 0;
  1005. if (!point0 && (v00 = v0 = v)) stream.lineStart();
  1006. if (v !== v0) {
  1007. point2 = intersect(point0, point1);
  1008. if (!point2 || pointEqual(point0, point2) || pointEqual(point1, point2))
  1009. point1[2] = 1;
  1010. }
  1011. if (v !== v0) {
  1012. clean = 0;
  1013. if (v) {
  1014. // outside going in
  1015. stream.lineStart();
  1016. point2 = intersect(point1, point0);
  1017. stream.point(point2[0], point2[1]);
  1018. } else {
  1019. // inside going out
  1020. point2 = intersect(point0, point1);
  1021. stream.point(point2[0], point2[1], 2);
  1022. stream.lineEnd();
  1023. }
  1024. point0 = point2;
  1025. } else if (notHemisphere && point0 && smallRadius ^ v) {
  1026. var t;
  1027. // If the codes for two points are different, or are both zero,
  1028. // and there this segment intersects with the small circle.
  1029. if (!(c & c0) && (t = intersect(point1, point0, true))) {
  1030. clean = 0;
  1031. if (smallRadius) {
  1032. stream.lineStart();
  1033. stream.point(t[0][0], t[0][1]);
  1034. stream.point(t[1][0], t[1][1]);
  1035. stream.lineEnd();
  1036. } else {
  1037. stream.point(t[1][0], t[1][1]);
  1038. stream.lineEnd();
  1039. stream.lineStart();
  1040. stream.point(t[0][0], t[0][1], 3);
  1041. }
  1042. }
  1043. }
  1044. if (v && (!point0 || !pointEqual(point0, point1))) {
  1045. stream.point(point1[0], point1[1]);
  1046. }
  1047. point0 = point1, v0 = v, c0 = c;
  1048. },
  1049. lineEnd: function() {
  1050. if (v0) stream.lineEnd();
  1051. point0 = null;
  1052. },
  1053. // Rejoin first and last segments if there were intersections and the first
  1054. // and last points were visible.
  1055. clean: function() {
  1056. return clean | ((v00 && v0) << 1);
  1057. }
  1058. };
  1059. }
  1060. // Intersects the great circle between a and b with the clip circle.
  1061. function intersect(a, b, two) {
  1062. var pa = cartesian(a),
  1063. pb = cartesian(b);
  1064. // We have two planes, n1.p = d1 and n2.p = d2.
  1065. // Find intersection line p(t) = c1 n1 + c2 n2 + t (n1 ⨯ n2).
  1066. var n1 = [1, 0, 0], // normal
  1067. n2 = cartesianCross(pa, pb),
  1068. n2n2 = cartesianDot(n2, n2),
  1069. n1n2 = n2[0], // cartesianDot(n1, n2),
  1070. determinant = n2n2 - n1n2 * n1n2;
  1071. // Two polar points.
  1072. if (!determinant) return !two && a;
  1073. var c1 = cr * n2n2 / determinant,
  1074. c2 = -cr * n1n2 / determinant,
  1075. n1xn2 = cartesianCross(n1, n2),
  1076. A = cartesianScale(n1, c1),
  1077. B = cartesianScale(n2, c2);
  1078. cartesianAddInPlace(A, B);
  1079. // Solve |p(t)|^2 = 1.
  1080. var u = n1xn2,
  1081. w = cartesianDot(A, u),
  1082. uu = cartesianDot(u, u),
  1083. t2 = w * w - uu * (cartesianDot(A, A) - 1);
  1084. if (t2 < 0) return;
  1085. var t = sqrt(t2),
  1086. q = cartesianScale(u, (-w - t) / uu);
  1087. cartesianAddInPlace(q, A);
  1088. q = spherical(q);
  1089. if (!two) return q;
  1090. // Two intersection points.
  1091. var lambda0 = a[0],
  1092. lambda1 = b[0],
  1093. phi0 = a[1],
  1094. phi1 = b[1],
  1095. z;
  1096. if (lambda1 < lambda0) z = lambda0, lambda0 = lambda1, lambda1 = z;
  1097. var delta = lambda1 - lambda0,
  1098. polar = abs(delta - pi) < epsilon,
  1099. meridian = polar || delta < epsilon;
  1100. if (!polar && phi1 < phi0) z = phi0, phi0 = phi1, phi1 = z;
  1101. // Check that the first point is between a and b.
  1102. if (meridian
  1103. ? polar
  1104. ? phi0 + phi1 > 0 ^ q[1] < (abs(q[0] - lambda0) < epsilon ? phi0 : phi1)
  1105. : phi0 <= q[1] && q[1] <= phi1
  1106. : delta > pi ^ (lambda0 <= q[0] && q[0] <= lambda1)) {
  1107. var q1 = cartesianScale(u, (-w + t) / uu);
  1108. cartesianAddInPlace(q1, A);
  1109. return [q, spherical(q1)];
  1110. }
  1111. }
  1112. // Generates a 4-bit vector representing the location of a point relative to
  1113. // the small circle's bounding box.
  1114. function code(lambda, phi) {
  1115. var r = smallRadius ? radius : pi - radius,
  1116. code = 0;
  1117. if (lambda < -r) code |= 1; // left
  1118. else if (lambda > r) code |= 2; // right
  1119. if (phi < -r) code |= 4; // below
  1120. else if (phi > r) code |= 8; // above
  1121. return code;
  1122. }
  1123. return clip(visible, clipLine, interpolate, smallRadius ? [0, -radius] : [-pi, radius - pi]);
  1124. }
  1125. function clipLine(a, b, x0, y0, x1, y1) {
  1126. var ax = a[0],
  1127. ay = a[1],
  1128. bx = b[0],
  1129. by = b[1],
  1130. t0 = 0,
  1131. t1 = 1,
  1132. dx = bx - ax,
  1133. dy = by - ay,
  1134. r;
  1135. r = x0 - ax;
  1136. if (!dx && r > 0) return;
  1137. r /= dx;
  1138. if (dx < 0) {
  1139. if (r < t0) return;
  1140. if (r < t1) t1 = r;
  1141. } else if (dx > 0) {
  1142. if (r > t1) return;
  1143. if (r > t0) t0 = r;
  1144. }
  1145. r = x1 - ax;
  1146. if (!dx && r < 0) return;
  1147. r /= dx;
  1148. if (dx < 0) {
  1149. if (r > t1) return;
  1150. if (r > t0) t0 = r;
  1151. } else if (dx > 0) {
  1152. if (r < t0) return;
  1153. if (r < t1) t1 = r;
  1154. }
  1155. r = y0 - ay;
  1156. if (!dy && r > 0) return;
  1157. r /= dy;
  1158. if (dy < 0) {
  1159. if (r < t0) return;
  1160. if (r < t1) t1 = r;
  1161. } else if (dy > 0) {
  1162. if (r > t1) return;
  1163. if (r > t0) t0 = r;
  1164. }
  1165. r = y1 - ay;
  1166. if (!dy && r < 0) return;
  1167. r /= dy;
  1168. if (dy < 0) {
  1169. if (r > t1) return;
  1170. if (r > t0) t0 = r;
  1171. } else if (dy > 0) {
  1172. if (r < t0) return;
  1173. if (r < t1) t1 = r;
  1174. }
  1175. if (t0 > 0) a[0] = ax + t0 * dx, a[1] = ay + t0 * dy;
  1176. if (t1 < 1) b[0] = ax + t1 * dx, b[1] = ay + t1 * dy;
  1177. return true;
  1178. }
  1179. var clipMax = 1e9, clipMin = -clipMax;
  1180. // TODO Use d3-polygon’s polygonContains here for the ring check?
  1181. // TODO Eliminate duplicate buffering in clipBuffer and polygon.push?
  1182. function clipRectangle(x0, y0, x1, y1) {
  1183. function visible(x, y) {
  1184. return x0 <= x && x <= x1 && y0 <= y && y <= y1;
  1185. }
  1186. function interpolate(from, to, direction, stream) {
  1187. var a = 0, a1 = 0;
  1188. if (from == null
  1189. || (a = corner(from, direction)) !== (a1 = corner(to, direction))
  1190. || comparePoint(from, to) < 0 ^ direction > 0) {
  1191. do stream.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0);
  1192. while ((a = (a + direction + 4) % 4) !== a1);
  1193. } else {
  1194. stream.point(to[0], to[1]);
  1195. }
  1196. }
  1197. function corner(p, direction) {
  1198. return abs(p[0] - x0) < epsilon ? direction > 0 ? 0 : 3
  1199. : abs(p[0] - x1) < epsilon ? direction > 0 ? 2 : 1
  1200. : abs(p[1] - y0) < epsilon ? direction > 0 ? 1 : 0
  1201. : direction > 0 ? 3 : 2; // abs(p[1] - y1) < epsilon
  1202. }
  1203. function compareIntersection(a, b) {
  1204. return comparePoint(a.x, b.x);
  1205. }
  1206. function comparePoint(a, b) {
  1207. var ca = corner(a, 1),
  1208. cb = corner(b, 1);
  1209. return ca !== cb ? ca - cb
  1210. : ca === 0 ? b[1] - a[1]
  1211. : ca === 1 ? a[0] - b[0]
  1212. : ca === 2 ? a[1] - b[1]
  1213. : b[0] - a[0];
  1214. }
  1215. return function(stream) {
  1216. var activeStream = stream,
  1217. bufferStream = clipBuffer(),
  1218. segments,
  1219. polygon,
  1220. ring,
  1221. x__, y__, v__, // first point
  1222. x_, y_, v_, // previous point
  1223. first,
  1224. clean;
  1225. var clipStream = {
  1226. point: point,
  1227. lineStart: lineStart,
  1228. lineEnd: lineEnd,
  1229. polygonStart: polygonStart,
  1230. polygonEnd: polygonEnd
  1231. };
  1232. function point(x, y) {
  1233. if (visible(x, y)) activeStream.point(x, y);
  1234. }
  1235. function polygonInside() {
  1236. var winding = 0;
  1237. for (var i = 0, n = polygon.length; i < n; ++i) {
  1238. for (var ring = polygon[i], j = 1, m = ring.length, point = ring[0], a0, a1, b0 = point[0], b1 = point[1]; j < m; ++j) {
  1239. a0 = b0, a1 = b1, point = ring[j], b0 = point[0], b1 = point[1];
  1240. if (a1 <= y1) { if (b1 > y1 && (b0 - a0) * (y1 - a1) > (b1 - a1) * (x0 - a0)) ++winding; }
  1241. else { if (b1 <= y1 && (b0 - a0) * (y1 - a1) < (b1 - a1) * (x0 - a0)) --winding; }
  1242. }
  1243. }
  1244. return winding;
  1245. }
  1246. // Buffer geometry within a polygon and then clip it en masse.
  1247. function polygonStart() {
  1248. activeStream = bufferStream, segments = [], polygon = [], clean = true;
  1249. }
  1250. function polygonEnd() {
  1251. var startInside = polygonInside(),
  1252. cleanInside = clean && startInside,
  1253. visible = (segments = d3Array.merge(segments)).length;
  1254. if (cleanInside || visible) {
  1255. stream.polygonStart();
  1256. if (cleanInside) {
  1257. stream.lineStart();
  1258. interpolate(null, null, 1, stream);
  1259. stream.lineEnd();
  1260. }
  1261. if (visible) {
  1262. clipRejoin(segments, compareIntersection, startInside, interpolate, stream);
  1263. }
  1264. stream.polygonEnd();
  1265. }
  1266. activeStream = stream, segments = polygon = ring = null;
  1267. }
  1268. function lineStart() {
  1269. clipStream.point = linePoint;
  1270. if (polygon) polygon.push(ring = []);
  1271. first = true;
  1272. v_ = false;
  1273. x_ = y_ = NaN;
  1274. }
  1275. // TODO rather than special-case polygons, simply handle them separately.
  1276. // Ideally, coincident intersection points should be jittered to avoid
  1277. // clipping issues.
  1278. function lineEnd() {
  1279. if (segments) {
  1280. linePoint(x__, y__);
  1281. if (v__ && v_) bufferStream.rejoin();
  1282. segments.push(bufferStream.result());
  1283. }
  1284. clipStream.point = point;
  1285. if (v_) activeStream.lineEnd();
  1286. }
  1287. function linePoint(x, y) {
  1288. var v = visible(x, y);
  1289. if (polygon) ring.push([x, y]);
  1290. if (first) {
  1291. x__ = x, y__ = y, v__ = v;
  1292. first = false;
  1293. if (v) {
  1294. activeStream.lineStart();
  1295. activeStream.point(x, y);
  1296. }
  1297. } else {
  1298. if (v && v_) activeStream.point(x, y);
  1299. else {
  1300. var a = [x_ = Math.max(clipMin, Math.min(clipMax, x_)), y_ = Math.max(clipMin, Math.min(clipMax, y_))],
  1301. b = [x = Math.max(clipMin, Math.min(clipMax, x)), y = Math.max(clipMin, Math.min(clipMax, y))];
  1302. if (clipLine(a, b, x0, y0, x1, y1)) {
  1303. if (!v_) {
  1304. activeStream.lineStart();
  1305. activeStream.point(a[0], a[1]);
  1306. }
  1307. activeStream.point(b[0], b[1]);
  1308. if (!v) activeStream.lineEnd();
  1309. clean = false;
  1310. } else if (v) {
  1311. activeStream.lineStart();
  1312. activeStream.point(x, y);
  1313. clean = false;
  1314. }
  1315. }
  1316. }
  1317. x_ = x, y_ = y, v_ = v;
  1318. }
  1319. return clipStream;
  1320. };
  1321. }
  1322. function extent() {
  1323. var x0 = 0,
  1324. y0 = 0,
  1325. x1 = 960,
  1326. y1 = 500,
  1327. cache,
  1328. cacheStream,
  1329. clip;
  1330. return clip = {
  1331. stream: function(stream) {
  1332. return cache && cacheStream === stream ? cache : cache = clipRectangle(x0, y0, x1, y1)(cacheStream = stream);
  1333. },
  1334. extent: function(_) {
  1335. return arguments.length ? (x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1], cache = cacheStream = null, clip) : [[x0, y0], [x1, y1]];
  1336. }
  1337. };
  1338. }
  1339. var lengthSum$1,
  1340. lambda0,
  1341. sinPhi0,
  1342. cosPhi0;
  1343. var lengthStream$1 = {
  1344. sphere: noop,
  1345. point: noop,
  1346. lineStart: lengthLineStart,
  1347. lineEnd: noop,
  1348. polygonStart: noop,
  1349. polygonEnd: noop
  1350. };
  1351. function lengthLineStart() {
  1352. lengthStream$1.point = lengthPointFirst$1;
  1353. lengthStream$1.lineEnd = lengthLineEnd;
  1354. }
  1355. function lengthLineEnd() {
  1356. lengthStream$1.point = lengthStream$1.lineEnd = noop;
  1357. }
  1358. function lengthPointFirst$1(lambda, phi) {
  1359. lambda *= radians, phi *= radians;
  1360. lambda0 = lambda, sinPhi0 = sin(phi), cosPhi0 = cos(phi);
  1361. lengthStream$1.point = lengthPoint$1;
  1362. }
  1363. function lengthPoint$1(lambda, phi) {
  1364. lambda *= radians, phi *= radians;
  1365. var sinPhi = sin(phi),
  1366. cosPhi = cos(phi),
  1367. delta = abs(lambda - lambda0),
  1368. cosDelta = cos(delta),
  1369. sinDelta = sin(delta),
  1370. x = cosPhi * sinDelta,
  1371. y = cosPhi0 * sinPhi - sinPhi0 * cosPhi * cosDelta,
  1372. z = sinPhi0 * sinPhi + cosPhi0 * cosPhi * cosDelta;
  1373. lengthSum$1.add(atan2(sqrt(x * x + y * y), z));
  1374. lambda0 = lambda, sinPhi0 = sinPhi, cosPhi0 = cosPhi;
  1375. }
  1376. function length(object) {
  1377. lengthSum$1 = new d3Array.Adder();
  1378. geoStream(object, lengthStream$1);
  1379. return +lengthSum$1;
  1380. }
  1381. var coordinates = [null, null],
  1382. object = {type: "LineString", coordinates: coordinates};
  1383. function distance(a, b) {
  1384. coordinates[0] = a;
  1385. coordinates[1] = b;
  1386. return length(object);
  1387. }
  1388. var containsObjectType = {
  1389. Feature: function(object, point) {
  1390. return containsGeometry(object.geometry, point);
  1391. },
  1392. FeatureCollection: function(object, point) {
  1393. var features = object.features, i = -1, n = features.length;
  1394. while (++i < n) if (containsGeometry(features[i].geometry, point)) return true;
  1395. return false;
  1396. }
  1397. };
  1398. var containsGeometryType = {
  1399. Sphere: function() {
  1400. return true;
  1401. },
  1402. Point: function(object, point) {
  1403. return containsPoint(object.coordinates, point);
  1404. },
  1405. MultiPoint: function(object, point) {
  1406. var coordinates = object.coordinates, i = -1, n = coordinates.length;
  1407. while (++i < n) if (containsPoint(coordinates[i], point)) return true;
  1408. return false;
  1409. },
  1410. LineString: function(object, point) {
  1411. return containsLine(object.coordinates, point);
  1412. },
  1413. MultiLineString: function(object, point) {
  1414. var coordinates = object.coordinates, i = -1, n = coordinates.length;
  1415. while (++i < n) if (containsLine(coordinates[i], point)) return true;
  1416. return false;
  1417. },
  1418. Polygon: function(object, point) {
  1419. return containsPolygon(object.coordinates, point);
  1420. },
  1421. MultiPolygon: function(object, point) {
  1422. var coordinates = object.coordinates, i = -1, n = coordinates.length;
  1423. while (++i < n) if (containsPolygon(coordinates[i], point)) return true;
  1424. return false;
  1425. },
  1426. GeometryCollection: function(object, point) {
  1427. var geometries = object.geometries, i = -1, n = geometries.length;
  1428. while (++i < n) if (containsGeometry(geometries[i], point)) return true;
  1429. return false;
  1430. }
  1431. };
  1432. function containsGeometry(geometry, point) {
  1433. return geometry && containsGeometryType.hasOwnProperty(geometry.type)
  1434. ? containsGeometryType[geometry.type](geometry, point)
  1435. : false;
  1436. }
  1437. function containsPoint(coordinates, point) {
  1438. return distance(coordinates, point) === 0;
  1439. }
  1440. function containsLine(coordinates, point) {
  1441. var ao, bo, ab;
  1442. for (var i = 0, n = coordinates.length; i < n; i++) {
  1443. bo = distance(coordinates[i], point);
  1444. if (bo === 0) return true;
  1445. if (i > 0) {
  1446. ab = distance(coordinates[i], coordinates[i - 1]);
  1447. if (
  1448. ab > 0 &&
  1449. ao <= ab &&
  1450. bo <= ab &&
  1451. (ao + bo - ab) * (1 - Math.pow((ao - bo) / ab, 2)) < epsilon2 * ab
  1452. )
  1453. return true;
  1454. }
  1455. ao = bo;
  1456. }
  1457. return false;
  1458. }
  1459. function containsPolygon(coordinates, point) {
  1460. return !!polygonContains(coordinates.map(ringRadians), pointRadians(point));
  1461. }
  1462. function ringRadians(ring) {
  1463. return ring = ring.map(pointRadians), ring.pop(), ring;
  1464. }
  1465. function pointRadians(point) {
  1466. return [point[0] * radians, point[1] * radians];
  1467. }
  1468. function contains(object, point) {
  1469. return (object && containsObjectType.hasOwnProperty(object.type)
  1470. ? containsObjectType[object.type]
  1471. : containsGeometry)(object, point);
  1472. }
  1473. function graticuleX(y0, y1, dy) {
  1474. var y = d3Array.range(y0, y1 - epsilon, dy).concat(y1);
  1475. return function(x) { return y.map(function(y) { return [x, y]; }); };
  1476. }
  1477. function graticuleY(x0, x1, dx) {
  1478. var x = d3Array.range(x0, x1 - epsilon, dx).concat(x1);
  1479. return function(y) { return x.map(function(x) { return [x, y]; }); };
  1480. }
  1481. function graticule() {
  1482. var x1, x0, X1, X0,
  1483. y1, y0, Y1, Y0,
  1484. dx = 10, dy = dx, DX = 90, DY = 360,
  1485. x, y, X, Y,
  1486. precision = 2.5;
  1487. function graticule() {
  1488. return {type: "MultiLineString", coordinates: lines()};
  1489. }
  1490. function lines() {
  1491. return d3Array.range(ceil(X0 / DX) * DX, X1, DX).map(X)
  1492. .concat(d3Array.range(ceil(Y0 / DY) * DY, Y1, DY).map(Y))
  1493. .concat(d3Array.range(ceil(x0 / dx) * dx, x1, dx).filter(function(x) { return abs(x % DX) > epsilon; }).map(x))
  1494. .concat(d3Array.range(ceil(y0 / dy) * dy, y1, dy).filter(function(y) { return abs(y % DY) > epsilon; }).map(y));
  1495. }
  1496. graticule.lines = function() {
  1497. return lines().map(function(coordinates) { return {type: "LineString", coordinates: coordinates}; });
  1498. };
  1499. graticule.outline = function() {
  1500. return {
  1501. type: "Polygon",
  1502. coordinates: [
  1503. X(X0).concat(
  1504. Y(Y1).slice(1),
  1505. X(X1).reverse().slice(1),
  1506. Y(Y0).reverse().slice(1))
  1507. ]
  1508. };
  1509. };
  1510. graticule.extent = function(_) {
  1511. if (!arguments.length) return graticule.extentMinor();
  1512. return graticule.extentMajor(_).extentMinor(_);
  1513. };
  1514. graticule.extentMajor = function(_) {
  1515. if (!arguments.length) return [[X0, Y0], [X1, Y1]];
  1516. X0 = +_[0][0], X1 = +_[1][0];
  1517. Y0 = +_[0][1], Y1 = +_[1][1];
  1518. if (X0 > X1) _ = X0, X0 = X1, X1 = _;
  1519. if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _;
  1520. return graticule.precision(precision);
  1521. };
  1522. graticule.extentMinor = function(_) {
  1523. if (!arguments.length) return [[x0, y0], [x1, y1]];
  1524. x0 = +_[0][0], x1 = +_[1][0];
  1525. y0 = +_[0][1], y1 = +_[1][1];
  1526. if (x0 > x1) _ = x0, x0 = x1, x1 = _;
  1527. if (y0 > y1) _ = y0, y0 = y1, y1 = _;
  1528. return graticule.precision(precision);
  1529. };
  1530. graticule.step = function(_) {
  1531. if (!arguments.length) return graticule.stepMinor();
  1532. return graticule.stepMajor(_).stepMinor(_);
  1533. };
  1534. graticule.stepMajor = function(_) {
  1535. if (!arguments.length) return [DX, DY];
  1536. DX = +_[0], DY = +_[1];
  1537. return graticule;
  1538. };
  1539. graticule.stepMinor = function(_) {
  1540. if (!arguments.length) return [dx, dy];
  1541. dx = +_[0], dy = +_[1];
  1542. return graticule;
  1543. };
  1544. graticule.precision = function(_) {
  1545. if (!arguments.length) return precision;
  1546. precision = +_;
  1547. x = graticuleX(y0, y1, 90);
  1548. y = graticuleY(x0, x1, precision);
  1549. X = graticuleX(Y0, Y1, 90);
  1550. Y = graticuleY(X0, X1, precision);
  1551. return graticule;
  1552. };
  1553. return graticule
  1554. .extentMajor([[-180, -90 + epsilon], [180, 90 - epsilon]])
  1555. .extentMinor([[-180, -80 - epsilon], [180, 80 + epsilon]]);
  1556. }
  1557. function graticule10() {
  1558. return graticule()();
  1559. }
  1560. function interpolate(a, b) {
  1561. var x0 = a[0] * radians,
  1562. y0 = a[1] * radians,
  1563. x1 = b[0] * radians,
  1564. y1 = b[1] * radians,
  1565. cy0 = cos(y0),
  1566. sy0 = sin(y0),
  1567. cy1 = cos(y1),
  1568. sy1 = sin(y1),
  1569. kx0 = cy0 * cos(x0),
  1570. ky0 = cy0 * sin(x0),
  1571. kx1 = cy1 * cos(x1),
  1572. ky1 = cy1 * sin(x1),
  1573. d = 2 * asin(sqrt(haversin(y1 - y0) + cy0 * cy1 * haversin(x1 - x0))),
  1574. k = sin(d);
  1575. var interpolate = d ? function(t) {
  1576. var B = sin(t *= d) / k,
  1577. A = sin(d - t) / k,
  1578. x = A * kx0 + B * kx1,
  1579. y = A * ky0 + B * ky1,
  1580. z = A * sy0 + B * sy1;
  1581. return [
  1582. atan2(y, x) * degrees,
  1583. atan2(z, sqrt(x * x + y * y)) * degrees
  1584. ];
  1585. } : function() {
  1586. return [x0 * degrees, y0 * degrees];
  1587. };
  1588. interpolate.distance = d;
  1589. return interpolate;
  1590. }
  1591. var identity$1 = x => x;
  1592. var areaSum = new d3Array.Adder(),
  1593. areaRingSum = new d3Array.Adder(),
  1594. x00$2,
  1595. y00$2,
  1596. x0$3,
  1597. y0$3;
  1598. var areaStream = {
  1599. point: noop,
  1600. lineStart: noop,
  1601. lineEnd: noop,
  1602. polygonStart: function() {
  1603. areaStream.lineStart = areaRingStart;
  1604. areaStream.lineEnd = areaRingEnd;
  1605. },
  1606. polygonEnd: function() {
  1607. areaStream.lineStart = areaStream.lineEnd = areaStream.point = noop;
  1608. areaSum.add(abs(areaRingSum));
  1609. areaRingSum = new d3Array.Adder();
  1610. },
  1611. result: function() {
  1612. var area = areaSum / 2;
  1613. areaSum = new d3Array.Adder();
  1614. return area;
  1615. }
  1616. };
  1617. function areaRingStart() {
  1618. areaStream.point = areaPointFirst;
  1619. }
  1620. function areaPointFirst(x, y) {
  1621. areaStream.point = areaPoint;
  1622. x00$2 = x0$3 = x, y00$2 = y0$3 = y;
  1623. }
  1624. function areaPoint(x, y) {
  1625. areaRingSum.add(y0$3 * x - x0$3 * y);
  1626. x0$3 = x, y0$3 = y;
  1627. }
  1628. function areaRingEnd() {
  1629. areaPoint(x00$2, y00$2);
  1630. }
  1631. var x0$2 = Infinity,
  1632. y0$2 = x0$2,
  1633. x1 = -x0$2,
  1634. y1 = x1;
  1635. var boundsStream = {
  1636. point: boundsPoint,
  1637. lineStart: noop,
  1638. lineEnd: noop,
  1639. polygonStart: noop,
  1640. polygonEnd: noop,
  1641. result: function() {
  1642. var bounds = [[x0$2, y0$2], [x1, y1]];
  1643. x1 = y1 = -(y0$2 = x0$2 = Infinity);
  1644. return bounds;
  1645. }
  1646. };
  1647. function boundsPoint(x, y) {
  1648. if (x < x0$2) x0$2 = x;
  1649. if (x > x1) x1 = x;
  1650. if (y < y0$2) y0$2 = y;
  1651. if (y > y1) y1 = y;
  1652. }
  1653. // TODO Enforce positive area for exterior, negative area for interior?
  1654. var X0 = 0,
  1655. Y0 = 0,
  1656. Z0 = 0,
  1657. X1 = 0,
  1658. Y1 = 0,
  1659. Z1 = 0,
  1660. X2 = 0,
  1661. Y2 = 0,
  1662. Z2 = 0,
  1663. x00$1,
  1664. y00$1,
  1665. x0$1,
  1666. y0$1;
  1667. var centroidStream = {
  1668. point: centroidPoint,
  1669. lineStart: centroidLineStart,
  1670. lineEnd: centroidLineEnd,
  1671. polygonStart: function() {
  1672. centroidStream.lineStart = centroidRingStart;
  1673. centroidStream.lineEnd = centroidRingEnd;
  1674. },
  1675. polygonEnd: function() {
  1676. centroidStream.point = centroidPoint;
  1677. centroidStream.lineStart = centroidLineStart;
  1678. centroidStream.lineEnd = centroidLineEnd;
  1679. },
  1680. result: function() {
  1681. var centroid = Z2 ? [X2 / Z2, Y2 / Z2]
  1682. : Z1 ? [X1 / Z1, Y1 / Z1]
  1683. : Z0 ? [X0 / Z0, Y0 / Z0]
  1684. : [NaN, NaN];
  1685. X0 = Y0 = Z0 =
  1686. X1 = Y1 = Z1 =
  1687. X2 = Y2 = Z2 = 0;
  1688. return centroid;
  1689. }
  1690. };
  1691. function centroidPoint(x, y) {
  1692. X0 += x;
  1693. Y0 += y;
  1694. ++Z0;
  1695. }
  1696. function centroidLineStart() {
  1697. centroidStream.point = centroidPointFirstLine;
  1698. }
  1699. function centroidPointFirstLine(x, y) {
  1700. centroidStream.point = centroidPointLine;
  1701. centroidPoint(x0$1 = x, y0$1 = y);
  1702. }
  1703. function centroidPointLine(x, y) {
  1704. var dx = x - x0$1, dy = y - y0$1, z = sqrt(dx * dx + dy * dy);
  1705. X1 += z * (x0$1 + x) / 2;
  1706. Y1 += z * (y0$1 + y) / 2;
  1707. Z1 += z;
  1708. centroidPoint(x0$1 = x, y0$1 = y);
  1709. }
  1710. function centroidLineEnd() {
  1711. centroidStream.point = centroidPoint;
  1712. }
  1713. function centroidRingStart() {
  1714. centroidStream.point = centroidPointFirstRing;
  1715. }
  1716. function centroidRingEnd() {
  1717. centroidPointRing(x00$1, y00$1);
  1718. }
  1719. function centroidPointFirstRing(x, y) {
  1720. centroidStream.point = centroidPointRing;
  1721. centroidPoint(x00$1 = x0$1 = x, y00$1 = y0$1 = y);
  1722. }
  1723. function centroidPointRing(x, y) {
  1724. var dx = x - x0$1,
  1725. dy = y - y0$1,
  1726. z = sqrt(dx * dx + dy * dy);
  1727. X1 += z * (x0$1 + x) / 2;
  1728. Y1 += z * (y0$1 + y) / 2;
  1729. Z1 += z;
  1730. z = y0$1 * x - x0$1 * y;
  1731. X2 += z * (x0$1 + x);
  1732. Y2 += z * (y0$1 + y);
  1733. Z2 += z * 3;
  1734. centroidPoint(x0$1 = x, y0$1 = y);
  1735. }
  1736. function PathContext(context) {
  1737. this._context = context;
  1738. }
  1739. PathContext.prototype = {
  1740. _radius: 4.5,
  1741. pointRadius: function(_) {
  1742. return this._radius = _, this;
  1743. },
  1744. polygonStart: function() {
  1745. this._line = 0;
  1746. },
  1747. polygonEnd: function() {
  1748. this._line = NaN;
  1749. },
  1750. lineStart: function() {
  1751. this._point = 0;
  1752. },
  1753. lineEnd: function() {
  1754. if (this._line === 0) this._context.closePath();
  1755. this._point = NaN;
  1756. },
  1757. point: function(x, y) {
  1758. switch (this._point) {
  1759. case 0: {
  1760. this._context.moveTo(x, y);
  1761. this._point = 1;
  1762. break;
  1763. }
  1764. case 1: {
  1765. this._context.lineTo(x, y);
  1766. break;
  1767. }
  1768. default: {
  1769. this._context.moveTo(x + this._radius, y);
  1770. this._context.arc(x, y, this._radius, 0, tau);
  1771. break;
  1772. }
  1773. }
  1774. },
  1775. result: noop
  1776. };
  1777. var lengthSum = new d3Array.Adder(),
  1778. lengthRing,
  1779. x00,
  1780. y00,
  1781. x0,
  1782. y0;
  1783. var lengthStream = {
  1784. point: noop,
  1785. lineStart: function() {
  1786. lengthStream.point = lengthPointFirst;
  1787. },
  1788. lineEnd: function() {
  1789. if (lengthRing) lengthPoint(x00, y00);
  1790. lengthStream.point = noop;
  1791. },
  1792. polygonStart: function() {
  1793. lengthRing = true;
  1794. },
  1795. polygonEnd: function() {
  1796. lengthRing = null;
  1797. },
  1798. result: function() {
  1799. var length = +lengthSum;
  1800. lengthSum = new d3Array.Adder();
  1801. return length;
  1802. }
  1803. };
  1804. function lengthPointFirst(x, y) {
  1805. lengthStream.point = lengthPoint;
  1806. x00 = x0 = x, y00 = y0 = y;
  1807. }
  1808. function lengthPoint(x, y) {
  1809. x0 -= x, y0 -= y;
  1810. lengthSum.add(sqrt(x0 * x0 + y0 * y0));
  1811. x0 = x, y0 = y;
  1812. }
  1813. // Simple caching for constant-radius points.
  1814. let cacheDigits, cacheAppend, cacheRadius, cacheCircle;
  1815. class PathString {
  1816. constructor(digits) {
  1817. this._append = digits == null ? append : appendRound(digits);
  1818. this._radius = 4.5;
  1819. this._ = "";
  1820. }
  1821. pointRadius(_) {
  1822. this._radius = +_;
  1823. return this;
  1824. }
  1825. polygonStart() {
  1826. this._line = 0;
  1827. }
  1828. polygonEnd() {
  1829. this._line = NaN;
  1830. }
  1831. lineStart() {
  1832. this._point = 0;
  1833. }
  1834. lineEnd() {
  1835. if (this._line === 0) this._ += "Z";
  1836. this._point = NaN;
  1837. }
  1838. point(x, y) {
  1839. switch (this._point) {
  1840. case 0: {
  1841. this._append`M${x},${y}`;
  1842. this._point = 1;
  1843. break;
  1844. }
  1845. case 1: {
  1846. this._append`L${x},${y}`;
  1847. break;
  1848. }
  1849. default: {
  1850. this._append`M${x},${y}`;
  1851. if (this._radius !== cacheRadius || this._append !== cacheAppend) {
  1852. const r = this._radius;
  1853. const s = this._;
  1854. this._ = ""; // stash the old string so we can cache the circle path fragment
  1855. this._append`m0,${r}a${r},${r} 0 1,1 0,${-2 * r}a${r},${r} 0 1,1 0,${2 * r}z`;
  1856. cacheRadius = r;
  1857. cacheAppend = this._append;
  1858. cacheCircle = this._;
  1859. this._ = s;
  1860. }
  1861. this._ += cacheCircle;
  1862. break;
  1863. }
  1864. }
  1865. }
  1866. result() {
  1867. const result = this._;
  1868. this._ = "";
  1869. return result.length ? result : null;
  1870. }
  1871. }
  1872. function append(strings) {
  1873. let i = 1;
  1874. this._ += strings[0];
  1875. for (const j = strings.length; i < j; ++i) {
  1876. this._ += arguments[i] + strings[i];
  1877. }
  1878. }
  1879. function appendRound(digits) {
  1880. const d = Math.floor(digits);
  1881. if (!(d >= 0)) throw new RangeError(`invalid digits: ${digits}`);
  1882. if (d > 15) return append;
  1883. if (d !== cacheDigits) {
  1884. const k = 10 ** d;
  1885. cacheDigits = d;
  1886. cacheAppend = function append(strings) {
  1887. let i = 1;
  1888. this._ += strings[0];
  1889. for (const j = strings.length; i < j; ++i) {
  1890. this._ += Math.round(arguments[i] * k) / k + strings[i];
  1891. }
  1892. };
  1893. }
  1894. return cacheAppend;
  1895. }
  1896. function index(projection, context) {
  1897. let digits = 3,
  1898. pointRadius = 4.5,
  1899. projectionStream,
  1900. contextStream;
  1901. function path(object) {
  1902. if (object) {
  1903. if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments));
  1904. geoStream(object, projectionStream(contextStream));
  1905. }
  1906. return contextStream.result();
  1907. }
  1908. path.area = function(object) {
  1909. geoStream(object, projectionStream(areaStream));
  1910. return areaStream.result();
  1911. };
  1912. path.measure = function(object) {
  1913. geoStream(object, projectionStream(lengthStream));
  1914. return lengthStream.result();
  1915. };
  1916. path.bounds = function(object) {
  1917. geoStream(object, projectionStream(boundsStream));
  1918. return boundsStream.result();
  1919. };
  1920. path.centroid = function(object) {
  1921. geoStream(object, projectionStream(centroidStream));
  1922. return centroidStream.result();
  1923. };
  1924. path.projection = function(_) {
  1925. if (!arguments.length) return projection;
  1926. projectionStream = _ == null ? (projection = null, identity$1) : (projection = _).stream;
  1927. return path;
  1928. };
  1929. path.context = function(_) {
  1930. if (!arguments.length) return context;
  1931. contextStream = _ == null ? (context = null, new PathString(digits)) : new PathContext(context = _);
  1932. if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius);
  1933. return path;
  1934. };
  1935. path.pointRadius = function(_) {
  1936. if (!arguments.length) return pointRadius;
  1937. pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_);
  1938. return path;
  1939. };
  1940. path.digits = function(_) {
  1941. if (!arguments.length) return digits;
  1942. if (_ == null) digits = null;
  1943. else {
  1944. const d = Math.floor(_);
  1945. if (!(d >= 0)) throw new RangeError(`invalid digits: ${_}`);
  1946. digits = d;
  1947. }
  1948. if (context === null) contextStream = new PathString(digits);
  1949. return path;
  1950. };
  1951. return path.projection(projection).digits(digits).context(context);
  1952. }
  1953. function transform(methods) {
  1954. return {
  1955. stream: transformer(methods)
  1956. };
  1957. }
  1958. function transformer(methods) {
  1959. return function(stream) {
  1960. var s = new TransformStream;
  1961. for (var key in methods) s[key] = methods[key];
  1962. s.stream = stream;
  1963. return s;
  1964. };
  1965. }
  1966. function TransformStream() {}
  1967. TransformStream.prototype = {
  1968. constructor: TransformStream,
  1969. point: function(x, y) { this.stream.point(x, y); },
  1970. sphere: function() { this.stream.sphere(); },
  1971. lineStart: function() { this.stream.lineStart(); },
  1972. lineEnd: function() { this.stream.lineEnd(); },
  1973. polygonStart: function() { this.stream.polygonStart(); },
  1974. polygonEnd: function() { this.stream.polygonEnd(); }
  1975. };
  1976. function fit(projection, fitBounds, object) {
  1977. var clip = projection.clipExtent && projection.clipExtent();
  1978. projection.scale(150).translate([0, 0]);
  1979. if (clip != null) projection.clipExtent(null);
  1980. geoStream(object, projection.stream(boundsStream));
  1981. fitBounds(boundsStream.result());
  1982. if (clip != null) projection.clipExtent(clip);
  1983. return projection;
  1984. }
  1985. function fitExtent(projection, extent, object) {
  1986. return fit(projection, function(b) {
  1987. var w = extent[1][0] - extent[0][0],
  1988. h = extent[1][1] - extent[0][1],
  1989. k = Math.min(w / (b[1][0] - b[0][0]), h / (b[1][1] - b[0][1])),
  1990. x = +extent[0][0] + (w - k * (b[1][0] + b[0][0])) / 2,
  1991. y = +extent[0][1] + (h - k * (b[1][1] + b[0][1])) / 2;
  1992. projection.scale(150 * k).translate([x, y]);
  1993. }, object);
  1994. }
  1995. function fitSize(projection, size, object) {
  1996. return fitExtent(projection, [[0, 0], size], object);
  1997. }
  1998. function fitWidth(projection, width, object) {
  1999. return fit(projection, function(b) {
  2000. var w = +width,
  2001. k = w / (b[1][0] - b[0][0]),
  2002. x = (w - k * (b[1][0] + b[0][0])) / 2,
  2003. y = -k * b[0][1];
  2004. projection.scale(150 * k).translate([x, y]);
  2005. }, object);
  2006. }
  2007. function fitHeight(projection, height, object) {
  2008. return fit(projection, function(b) {
  2009. var h = +height,
  2010. k = h / (b[1][1] - b[0][1]),
  2011. x = -k * b[0][0],
  2012. y = (h - k * (b[1][1] + b[0][1])) / 2;
  2013. projection.scale(150 * k).translate([x, y]);
  2014. }, object);
  2015. }
  2016. var maxDepth = 16, // maximum depth of subdivision
  2017. cosMinDistance = cos(30 * radians); // cos(minimum angular distance)
  2018. function resample(project, delta2) {
  2019. return +delta2 ? resample$1(project, delta2) : resampleNone(project);
  2020. }
  2021. function resampleNone(project) {
  2022. return transformer({
  2023. point: function(x, y) {
  2024. x = project(x, y);
  2025. this.stream.point(x[0], x[1]);
  2026. }
  2027. });
  2028. }
  2029. function resample$1(project, delta2) {
  2030. function resampleLineTo(x0, y0, lambda0, a0, b0, c0, x1, y1, lambda1, a1, b1, c1, depth, stream) {
  2031. var dx = x1 - x0,
  2032. dy = y1 - y0,
  2033. d2 = dx * dx + dy * dy;
  2034. if (d2 > 4 * delta2 && depth--) {
  2035. var a = a0 + a1,
  2036. b = b0 + b1,
  2037. c = c0 + c1,
  2038. m = sqrt(a * a + b * b + c * c),
  2039. phi2 = asin(c /= m),
  2040. lambda2 = abs(abs(c) - 1) < epsilon || abs(lambda0 - lambda1) < epsilon ? (lambda0 + lambda1) / 2 : atan2(b, a),
  2041. p = project(lambda2, phi2),
  2042. x2 = p[0],
  2043. y2 = p[1],
  2044. dx2 = x2 - x0,
  2045. dy2 = y2 - y0,
  2046. dz = dy * dx2 - dx * dy2;
  2047. if (dz * dz / d2 > delta2 // perpendicular projected distance
  2048. || abs((dx * dx2 + dy * dy2) / d2 - 0.5) > 0.3 // midpoint close to an end
  2049. || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) { // angular distance
  2050. resampleLineTo(x0, y0, lambda0, a0, b0, c0, x2, y2, lambda2, a /= m, b /= m, c, depth, stream);
  2051. stream.point(x2, y2);
  2052. resampleLineTo(x2, y2, lambda2, a, b, c, x1, y1, lambda1, a1, b1, c1, depth, stream);
  2053. }
  2054. }
  2055. }
  2056. return function(stream) {
  2057. var lambda00, x00, y00, a00, b00, c00, // first point
  2058. lambda0, x0, y0, a0, b0, c0; // previous point
  2059. var resampleStream = {
  2060. point: point,
  2061. lineStart: lineStart,
  2062. lineEnd: lineEnd,
  2063. polygonStart: function() { stream.polygonStart(); resampleStream.lineStart = ringStart; },
  2064. polygonEnd: function() { stream.polygonEnd(); resampleStream.lineStart = lineStart; }
  2065. };
  2066. function point(x, y) {
  2067. x = project(x, y);
  2068. stream.point(x[0], x[1]);
  2069. }
  2070. function lineStart() {
  2071. x0 = NaN;
  2072. resampleStream.point = linePoint;
  2073. stream.lineStart();
  2074. }
  2075. function linePoint(lambda, phi) {
  2076. var c = cartesian([lambda, phi]), p = project(lambda, phi);
  2077. resampleLineTo(x0, y0, lambda0, a0, b0, c0, x0 = p[0], y0 = p[1], lambda0 = lambda, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream);
  2078. stream.point(x0, y0);
  2079. }
  2080. function lineEnd() {
  2081. resampleStream.point = point;
  2082. stream.lineEnd();
  2083. }
  2084. function ringStart() {
  2085. lineStart();
  2086. resampleStream.point = ringPoint;
  2087. resampleStream.lineEnd = ringEnd;
  2088. }
  2089. function ringPoint(lambda, phi) {
  2090. linePoint(lambda00 = lambda, phi), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0;
  2091. resampleStream.point = linePoint;
  2092. }
  2093. function ringEnd() {
  2094. resampleLineTo(x0, y0, lambda0, a0, b0, c0, x00, y00, lambda00, a00, b00, c00, maxDepth, stream);
  2095. resampleStream.lineEnd = lineEnd;
  2096. lineEnd();
  2097. }
  2098. return resampleStream;
  2099. };
  2100. }
  2101. var transformRadians = transformer({
  2102. point: function(x, y) {
  2103. this.stream.point(x * radians, y * radians);
  2104. }
  2105. });
  2106. function transformRotate(rotate) {
  2107. return transformer({
  2108. point: function(x, y) {
  2109. var r = rotate(x, y);
  2110. return this.stream.point(r[0], r[1]);
  2111. }
  2112. });
  2113. }
  2114. function scaleTranslate(k, dx, dy, sx, sy) {
  2115. function transform(x, y) {
  2116. x *= sx; y *= sy;
  2117. return [dx + k * x, dy - k * y];
  2118. }
  2119. transform.invert = function(x, y) {
  2120. return [(x - dx) / k * sx, (dy - y) / k * sy];
  2121. };
  2122. return transform;
  2123. }
  2124. function scaleTranslateRotate(k, dx, dy, sx, sy, alpha) {
  2125. if (!alpha) return scaleTranslate(k, dx, dy, sx, sy);
  2126. var cosAlpha = cos(alpha),
  2127. sinAlpha = sin(alpha),
  2128. a = cosAlpha * k,
  2129. b = sinAlpha * k,
  2130. ai = cosAlpha / k,
  2131. bi = sinAlpha / k,
  2132. ci = (sinAlpha * dy - cosAlpha * dx) / k,
  2133. fi = (sinAlpha * dx + cosAlpha * dy) / k;
  2134. function transform(x, y) {
  2135. x *= sx; y *= sy;
  2136. return [a * x - b * y + dx, dy - b * x - a * y];
  2137. }
  2138. transform.invert = function(x, y) {
  2139. return [sx * (ai * x - bi * y + ci), sy * (fi - bi * x - ai * y)];
  2140. };
  2141. return transform;
  2142. }
  2143. function projection(project) {
  2144. return projectionMutator(function() { return project; })();
  2145. }
  2146. function projectionMutator(projectAt) {
  2147. var project,
  2148. k = 150, // scale
  2149. x = 480, y = 250, // translate
  2150. lambda = 0, phi = 0, // center
  2151. deltaLambda = 0, deltaPhi = 0, deltaGamma = 0, rotate, // pre-rotate
  2152. alpha = 0, // post-rotate angle
  2153. sx = 1, // reflectX
  2154. sy = 1, // reflectX
  2155. theta = null, preclip = clipAntimeridian, // pre-clip angle
  2156. x0 = null, y0, x1, y1, postclip = identity$1, // post-clip extent
  2157. delta2 = 0.5, // precision
  2158. projectResample,
  2159. projectTransform,
  2160. projectRotateTransform,
  2161. cache,
  2162. cacheStream;
  2163. function projection(point) {
  2164. return projectRotateTransform(point[0] * radians, point[1] * radians);
  2165. }
  2166. function invert(point) {
  2167. point = projectRotateTransform.invert(point[0], point[1]);
  2168. return point && [point[0] * degrees, point[1] * degrees];
  2169. }
  2170. projection.stream = function(stream) {
  2171. return cache && cacheStream === stream ? cache : cache = transformRadians(transformRotate(rotate)(preclip(projectResample(postclip(cacheStream = stream)))));
  2172. };
  2173. projection.preclip = function(_) {
  2174. return arguments.length ? (preclip = _, theta = undefined, reset()) : preclip;
  2175. };
  2176. projection.postclip = function(_) {
  2177. return arguments.length ? (postclip = _, x0 = y0 = x1 = y1 = null, reset()) : postclip;
  2178. };
  2179. projection.clipAngle = function(_) {
  2180. return arguments.length ? (preclip = +_ ? clipCircle(theta = _ * radians) : (theta = null, clipAntimeridian), reset()) : theta * degrees;
  2181. };
  2182. projection.clipExtent = function(_) {
  2183. return arguments.length ? (postclip = _ == null ? (x0 = y0 = x1 = y1 = null, identity$1) : clipRectangle(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]), reset()) : x0 == null ? null : [[x0, y0], [x1, y1]];
  2184. };
  2185. projection.scale = function(_) {
  2186. return arguments.length ? (k = +_, recenter()) : k;
  2187. };
  2188. projection.translate = function(_) {
  2189. return arguments.length ? (x = +_[0], y = +_[1], recenter()) : [x, y];
  2190. };
  2191. projection.center = function(_) {
  2192. return arguments.length ? (lambda = _[0] % 360 * radians, phi = _[1] % 360 * radians, recenter()) : [lambda * degrees, phi * degrees];
  2193. };
  2194. projection.rotate = function(_) {
  2195. return arguments.length ? (deltaLambda = _[0] % 360 * radians, deltaPhi = _[1] % 360 * radians, deltaGamma = _.length > 2 ? _[2] % 360 * radians : 0, recenter()) : [deltaLambda * degrees, deltaPhi * degrees, deltaGamma * degrees];
  2196. };
  2197. projection.angle = function(_) {
  2198. return arguments.length ? (alpha = _ % 360 * radians, recenter()) : alpha * degrees;
  2199. };
  2200. projection.reflectX = function(_) {
  2201. return arguments.length ? (sx = _ ? -1 : 1, recenter()) : sx < 0;
  2202. };
  2203. projection.reflectY = function(_) {
  2204. return arguments.length ? (sy = _ ? -1 : 1, recenter()) : sy < 0;
  2205. };
  2206. projection.precision = function(_) {
  2207. return arguments.length ? (projectResample = resample(projectTransform, delta2 = _ * _), reset()) : sqrt(delta2);
  2208. };
  2209. projection.fitExtent = function(extent, object) {
  2210. return fitExtent(projection, extent, object);
  2211. };
  2212. projection.fitSize = function(size, object) {
  2213. return fitSize(projection, size, object);
  2214. };
  2215. projection.fitWidth = function(width, object) {
  2216. return fitWidth(projection, width, object);
  2217. };
  2218. projection.fitHeight = function(height, object) {
  2219. return fitHeight(projection, height, object);
  2220. };
  2221. function recenter() {
  2222. var center = scaleTranslateRotate(k, 0, 0, sx, sy, alpha).apply(null, project(lambda, phi)),
  2223. transform = scaleTranslateRotate(k, x - center[0], y - center[1], sx, sy, alpha);
  2224. rotate = rotateRadians(deltaLambda, deltaPhi, deltaGamma);
  2225. projectTransform = compose(project, transform);
  2226. projectRotateTransform = compose(rotate, projectTransform);
  2227. projectResample = resample(projectTransform, delta2);
  2228. return reset();
  2229. }
  2230. function reset() {
  2231. cache = cacheStream = null;
  2232. return projection;
  2233. }
  2234. return function() {
  2235. project = projectAt.apply(this, arguments);
  2236. projection.invert = project.invert && invert;
  2237. return recenter();
  2238. };
  2239. }
  2240. function conicProjection(projectAt) {
  2241. var phi0 = 0,
  2242. phi1 = pi / 3,
  2243. m = projectionMutator(projectAt),
  2244. p = m(phi0, phi1);
  2245. p.parallels = function(_) {
  2246. return arguments.length ? m(phi0 = _[0] * radians, phi1 = _[1] * radians) : [phi0 * degrees, phi1 * degrees];
  2247. };
  2248. return p;
  2249. }
  2250. function cylindricalEqualAreaRaw(phi0) {
  2251. var cosPhi0 = cos(phi0);
  2252. function forward(lambda, phi) {
  2253. return [lambda * cosPhi0, sin(phi) / cosPhi0];
  2254. }
  2255. forward.invert = function(x, y) {
  2256. return [x / cosPhi0, asin(y * cosPhi0)];
  2257. };
  2258. return forward;
  2259. }
  2260. function conicEqualAreaRaw(y0, y1) {
  2261. var sy0 = sin(y0), n = (sy0 + sin(y1)) / 2;
  2262. // Are the parallels symmetrical around the Equator?
  2263. if (abs(n) < epsilon) return cylindricalEqualAreaRaw(y0);
  2264. var c = 1 + sy0 * (2 * n - sy0), r0 = sqrt(c) / n;
  2265. function project(x, y) {
  2266. var r = sqrt(c - 2 * n * sin(y)) / n;
  2267. return [r * sin(x *= n), r0 - r * cos(x)];
  2268. }
  2269. project.invert = function(x, y) {
  2270. var r0y = r0 - y,
  2271. l = atan2(x, abs(r0y)) * sign(r0y);
  2272. if (r0y * n < 0)
  2273. l -= pi * sign(x) * sign(r0y);
  2274. return [l / n, asin((c - (x * x + r0y * r0y) * n * n) / (2 * n))];
  2275. };
  2276. return project;
  2277. }
  2278. function conicEqualArea() {
  2279. return conicProjection(conicEqualAreaRaw)
  2280. .scale(155.424)
  2281. .center([0, 33.6442]);
  2282. }
  2283. function albers() {
  2284. return conicEqualArea()
  2285. .parallels([29.5, 45.5])
  2286. .scale(1070)
  2287. .translate([480, 250])
  2288. .rotate([96, 0])
  2289. .center([-0.6, 38.7]);
  2290. }
  2291. // The projections must have mutually exclusive clip regions on the sphere,
  2292. // as this will avoid emitting interleaving lines and polygons.
  2293. function multiplex(streams) {
  2294. var n = streams.length;
  2295. return {
  2296. point: function(x, y) { var i = -1; while (++i < n) streams[i].point(x, y); },
  2297. sphere: function() { var i = -1; while (++i < n) streams[i].sphere(); },
  2298. lineStart: function() { var i = -1; while (++i < n) streams[i].lineStart(); },
  2299. lineEnd: function() { var i = -1; while (++i < n) streams[i].lineEnd(); },
  2300. polygonStart: function() { var i = -1; while (++i < n) streams[i].polygonStart(); },
  2301. polygonEnd: function() { var i = -1; while (++i < n) streams[i].polygonEnd(); }
  2302. };
  2303. }
  2304. // A composite projection for the United States, configured by default for
  2305. // 960×500. The projection also works quite well at 960×600 if you change the
  2306. // scale to 1285 and adjust the translate accordingly. The set of standard
  2307. // parallels for each region comes from USGS, which is published here:
  2308. // http://egsc.usgs.gov/isb/pubs/MapProjections/projections.html#albers
  2309. function albersUsa() {
  2310. var cache,
  2311. cacheStream,
  2312. lower48 = albers(), lower48Point,
  2313. alaska = conicEqualArea().rotate([154, 0]).center([-2, 58.5]).parallels([55, 65]), alaskaPoint, // EPSG:3338
  2314. hawaii = conicEqualArea().rotate([157, 0]).center([-3, 19.9]).parallels([8, 18]), hawaiiPoint, // ESRI:102007
  2315. point, pointStream = {point: function(x, y) { point = [x, y]; }};
  2316. function albersUsa(coordinates) {
  2317. var x = coordinates[0], y = coordinates[1];
  2318. return point = null,
  2319. (lower48Point.point(x, y), point)
  2320. || (alaskaPoint.point(x, y), point)
  2321. || (hawaiiPoint.point(x, y), point);
  2322. }
  2323. albersUsa.invert = function(coordinates) {
  2324. var k = lower48.scale(),
  2325. t = lower48.translate(),
  2326. x = (coordinates[0] - t[0]) / k,
  2327. y = (coordinates[1] - t[1]) / k;
  2328. return (y >= 0.120 && y < 0.234 && x >= -0.425 && x < -0.214 ? alaska
  2329. : y >= 0.166 && y < 0.234 && x >= -0.214 && x < -0.115 ? hawaii
  2330. : lower48).invert(coordinates);
  2331. };
  2332. albersUsa.stream = function(stream) {
  2333. return cache && cacheStream === stream ? cache : cache = multiplex([lower48.stream(cacheStream = stream), alaska.stream(stream), hawaii.stream(stream)]);
  2334. };
  2335. albersUsa.precision = function(_) {
  2336. if (!arguments.length) return lower48.precision();
  2337. lower48.precision(_), alaska.precision(_), hawaii.precision(_);
  2338. return reset();
  2339. };
  2340. albersUsa.scale = function(_) {
  2341. if (!arguments.length) return lower48.scale();
  2342. lower48.scale(_), alaska.scale(_ * 0.35), hawaii.scale(_);
  2343. return albersUsa.translate(lower48.translate());
  2344. };
  2345. albersUsa.translate = function(_) {
  2346. if (!arguments.length) return lower48.translate();
  2347. var k = lower48.scale(), x = +_[0], y = +_[1];
  2348. lower48Point = lower48
  2349. .translate(_)
  2350. .clipExtent([[x - 0.455 * k, y - 0.238 * k], [x + 0.455 * k, y + 0.238 * k]])
  2351. .stream(pointStream);
  2352. alaskaPoint = alaska
  2353. .translate([x - 0.307 * k, y + 0.201 * k])
  2354. .clipExtent([[x - 0.425 * k + epsilon, y + 0.120 * k + epsilon], [x - 0.214 * k - epsilon, y + 0.234 * k - epsilon]])
  2355. .stream(pointStream);
  2356. hawaiiPoint = hawaii
  2357. .translate([x - 0.205 * k, y + 0.212 * k])
  2358. .clipExtent([[x - 0.214 * k + epsilon, y + 0.166 * k + epsilon], [x - 0.115 * k - epsilon, y + 0.234 * k - epsilon]])
  2359. .stream(pointStream);
  2360. return reset();
  2361. };
  2362. albersUsa.fitExtent = function(extent, object) {
  2363. return fitExtent(albersUsa, extent, object);
  2364. };
  2365. albersUsa.fitSize = function(size, object) {
  2366. return fitSize(albersUsa, size, object);
  2367. };
  2368. albersUsa.fitWidth = function(width, object) {
  2369. return fitWidth(albersUsa, width, object);
  2370. };
  2371. albersUsa.fitHeight = function(height, object) {
  2372. return fitHeight(albersUsa, height, object);
  2373. };
  2374. function reset() {
  2375. cache = cacheStream = null;
  2376. return albersUsa;
  2377. }
  2378. return albersUsa.scale(1070);
  2379. }
  2380. function azimuthalRaw(scale) {
  2381. return function(x, y) {
  2382. var cx = cos(x),
  2383. cy = cos(y),
  2384. k = scale(cx * cy);
  2385. if (k === Infinity) return [2, 0];
  2386. return [
  2387. k * cy * sin(x),
  2388. k * sin(y)
  2389. ];
  2390. }
  2391. }
  2392. function azimuthalInvert(angle) {
  2393. return function(x, y) {
  2394. var z = sqrt(x * x + y * y),
  2395. c = angle(z),
  2396. sc = sin(c),
  2397. cc = cos(c);
  2398. return [
  2399. atan2(x * sc, z * cc),
  2400. asin(z && y * sc / z)
  2401. ];
  2402. }
  2403. }
  2404. var azimuthalEqualAreaRaw = azimuthalRaw(function(cxcy) {
  2405. return sqrt(2 / (1 + cxcy));
  2406. });
  2407. azimuthalEqualAreaRaw.invert = azimuthalInvert(function(z) {
  2408. return 2 * asin(z / 2);
  2409. });
  2410. function azimuthalEqualArea() {
  2411. return projection(azimuthalEqualAreaRaw)
  2412. .scale(124.75)
  2413. .clipAngle(180 - 1e-3);
  2414. }
  2415. var azimuthalEquidistantRaw = azimuthalRaw(function(c) {
  2416. return (c = acos(c)) && c / sin(c);
  2417. });
  2418. azimuthalEquidistantRaw.invert = azimuthalInvert(function(z) {
  2419. return z;
  2420. });
  2421. function azimuthalEquidistant() {
  2422. return projection(azimuthalEquidistantRaw)
  2423. .scale(79.4188)
  2424. .clipAngle(180 - 1e-3);
  2425. }
  2426. function mercatorRaw(lambda, phi) {
  2427. return [lambda, log(tan((halfPi + phi) / 2))];
  2428. }
  2429. mercatorRaw.invert = function(x, y) {
  2430. return [x, 2 * atan(exp(y)) - halfPi];
  2431. };
  2432. function mercator() {
  2433. return mercatorProjection(mercatorRaw)
  2434. .scale(961 / tau);
  2435. }
  2436. function mercatorProjection(project) {
  2437. var m = projection(project),
  2438. center = m.center,
  2439. scale = m.scale,
  2440. translate = m.translate,
  2441. clipExtent = m.clipExtent,
  2442. x0 = null, y0, x1, y1; // clip extent
  2443. m.scale = function(_) {
  2444. return arguments.length ? (scale(_), reclip()) : scale();
  2445. };
  2446. m.translate = function(_) {
  2447. return arguments.length ? (translate(_), reclip()) : translate();
  2448. };
  2449. m.center = function(_) {
  2450. return arguments.length ? (center(_), reclip()) : center();
  2451. };
  2452. m.clipExtent = function(_) {
  2453. return arguments.length ? ((_ == null ? x0 = y0 = x1 = y1 = null : (x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1])), reclip()) : x0 == null ? null : [[x0, y0], [x1, y1]];
  2454. };
  2455. function reclip() {
  2456. var k = pi * scale(),
  2457. t = m(rotation(m.rotate()).invert([0, 0]));
  2458. return clipExtent(x0 == null
  2459. ? [[t[0] - k, t[1] - k], [t[0] + k, t[1] + k]] : project === mercatorRaw
  2460. ? [[Math.max(t[0] - k, x0), y0], [Math.min(t[0] + k, x1), y1]]
  2461. : [[x0, Math.max(t[1] - k, y0)], [x1, Math.min(t[1] + k, y1)]]);
  2462. }
  2463. return reclip();
  2464. }
  2465. function tany(y) {
  2466. return tan((halfPi + y) / 2);
  2467. }
  2468. function conicConformalRaw(y0, y1) {
  2469. var cy0 = cos(y0),
  2470. n = y0 === y1 ? sin(y0) : log(cy0 / cos(y1)) / log(tany(y1) / tany(y0)),
  2471. f = cy0 * pow(tany(y0), n) / n;
  2472. if (!n) return mercatorRaw;
  2473. function project(x, y) {
  2474. if (f > 0) { if (y < -halfPi + epsilon) y = -halfPi + epsilon; }
  2475. else { if (y > halfPi - epsilon) y = halfPi - epsilon; }
  2476. var r = f / pow(tany(y), n);
  2477. return [r * sin(n * x), f - r * cos(n * x)];
  2478. }
  2479. project.invert = function(x, y) {
  2480. var fy = f - y, r = sign(n) * sqrt(x * x + fy * fy),
  2481. l = atan2(x, abs(fy)) * sign(fy);
  2482. if (fy * n < 0)
  2483. l -= pi * sign(x) * sign(fy);
  2484. return [l / n, 2 * atan(pow(f / r, 1 / n)) - halfPi];
  2485. };
  2486. return project;
  2487. }
  2488. function conicConformal() {
  2489. return conicProjection(conicConformalRaw)
  2490. .scale(109.5)
  2491. .parallels([30, 30]);
  2492. }
  2493. function equirectangularRaw(lambda, phi) {
  2494. return [lambda, phi];
  2495. }
  2496. equirectangularRaw.invert = equirectangularRaw;
  2497. function equirectangular() {
  2498. return projection(equirectangularRaw)
  2499. .scale(152.63);
  2500. }
  2501. function conicEquidistantRaw(y0, y1) {
  2502. var cy0 = cos(y0),
  2503. n = y0 === y1 ? sin(y0) : (cy0 - cos(y1)) / (y1 - y0),
  2504. g = cy0 / n + y0;
  2505. if (abs(n) < epsilon) return equirectangularRaw;
  2506. function project(x, y) {
  2507. var gy = g - y, nx = n * x;
  2508. return [gy * sin(nx), g - gy * cos(nx)];
  2509. }
  2510. project.invert = function(x, y) {
  2511. var gy = g - y,
  2512. l = atan2(x, abs(gy)) * sign(gy);
  2513. if (gy * n < 0)
  2514. l -= pi * sign(x) * sign(gy);
  2515. return [l / n, g - sign(n) * sqrt(x * x + gy * gy)];
  2516. };
  2517. return project;
  2518. }
  2519. function conicEquidistant() {
  2520. return conicProjection(conicEquidistantRaw)
  2521. .scale(131.154)
  2522. .center([0, 13.9389]);
  2523. }
  2524. var A1 = 1.340264,
  2525. A2 = -0.081106,
  2526. A3 = 0.000893,
  2527. A4 = 0.003796,
  2528. M = sqrt(3) / 2,
  2529. iterations = 12;
  2530. function equalEarthRaw(lambda, phi) {
  2531. var l = asin(M * sin(phi)), l2 = l * l, l6 = l2 * l2 * l2;
  2532. return [
  2533. lambda * cos(l) / (M * (A1 + 3 * A2 * l2 + l6 * (7 * A3 + 9 * A4 * l2))),
  2534. l * (A1 + A2 * l2 + l6 * (A3 + A4 * l2))
  2535. ];
  2536. }
  2537. equalEarthRaw.invert = function(x, y) {
  2538. var l = y, l2 = l * l, l6 = l2 * l2 * l2;
  2539. for (var i = 0, delta, fy, fpy; i < iterations; ++i) {
  2540. fy = l * (A1 + A2 * l2 + l6 * (A3 + A4 * l2)) - y;
  2541. fpy = A1 + 3 * A2 * l2 + l6 * (7 * A3 + 9 * A4 * l2);
  2542. l -= delta = fy / fpy, l2 = l * l, l6 = l2 * l2 * l2;
  2543. if (abs(delta) < epsilon2) break;
  2544. }
  2545. return [
  2546. M * x * (A1 + 3 * A2 * l2 + l6 * (7 * A3 + 9 * A4 * l2)) / cos(l),
  2547. asin(sin(l) / M)
  2548. ];
  2549. };
  2550. function equalEarth() {
  2551. return projection(equalEarthRaw)
  2552. .scale(177.158);
  2553. }
  2554. function gnomonicRaw(x, y) {
  2555. var cy = cos(y), k = cos(x) * cy;
  2556. return [cy * sin(x) / k, sin(y) / k];
  2557. }
  2558. gnomonicRaw.invert = azimuthalInvert(atan);
  2559. function gnomonic() {
  2560. return projection(gnomonicRaw)
  2561. .scale(144.049)
  2562. .clipAngle(60);
  2563. }
  2564. function identity() {
  2565. var k = 1, tx = 0, ty = 0, sx = 1, sy = 1, // scale, translate and reflect
  2566. alpha = 0, ca, sa, // angle
  2567. x0 = null, y0, x1, y1, // clip extent
  2568. kx = 1, ky = 1,
  2569. transform = transformer({
  2570. point: function(x, y) {
  2571. var p = projection([x, y]);
  2572. this.stream.point(p[0], p[1]);
  2573. }
  2574. }),
  2575. postclip = identity$1,
  2576. cache,
  2577. cacheStream;
  2578. function reset() {
  2579. kx = k * sx;
  2580. ky = k * sy;
  2581. cache = cacheStream = null;
  2582. return projection;
  2583. }
  2584. function projection (p) {
  2585. var x = p[0] * kx, y = p[1] * ky;
  2586. if (alpha) {
  2587. var t = y * ca - x * sa;
  2588. x = x * ca + y * sa;
  2589. y = t;
  2590. }
  2591. return [x + tx, y + ty];
  2592. }
  2593. projection.invert = function(p) {
  2594. var x = p[0] - tx, y = p[1] - ty;
  2595. if (alpha) {
  2596. var t = y * ca + x * sa;
  2597. x = x * ca - y * sa;
  2598. y = t;
  2599. }
  2600. return [x / kx, y / ky];
  2601. };
  2602. projection.stream = function(stream) {
  2603. return cache && cacheStream === stream ? cache : cache = transform(postclip(cacheStream = stream));
  2604. };
  2605. projection.postclip = function(_) {
  2606. return arguments.length ? (postclip = _, x0 = y0 = x1 = y1 = null, reset()) : postclip;
  2607. };
  2608. projection.clipExtent = function(_) {
  2609. return arguments.length ? (postclip = _ == null ? (x0 = y0 = x1 = y1 = null, identity$1) : clipRectangle(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]), reset()) : x0 == null ? null : [[x0, y0], [x1, y1]];
  2610. };
  2611. projection.scale = function(_) {
  2612. return arguments.length ? (k = +_, reset()) : k;
  2613. };
  2614. projection.translate = function(_) {
  2615. return arguments.length ? (tx = +_[0], ty = +_[1], reset()) : [tx, ty];
  2616. };
  2617. projection.angle = function(_) {
  2618. return arguments.length ? (alpha = _ % 360 * radians, sa = sin(alpha), ca = cos(alpha), reset()) : alpha * degrees;
  2619. };
  2620. projection.reflectX = function(_) {
  2621. return arguments.length ? (sx = _ ? -1 : 1, reset()) : sx < 0;
  2622. };
  2623. projection.reflectY = function(_) {
  2624. return arguments.length ? (sy = _ ? -1 : 1, reset()) : sy < 0;
  2625. };
  2626. projection.fitExtent = function(extent, object) {
  2627. return fitExtent(projection, extent, object);
  2628. };
  2629. projection.fitSize = function(size, object) {
  2630. return fitSize(projection, size, object);
  2631. };
  2632. projection.fitWidth = function(width, object) {
  2633. return fitWidth(projection, width, object);
  2634. };
  2635. projection.fitHeight = function(height, object) {
  2636. return fitHeight(projection, height, object);
  2637. };
  2638. return projection;
  2639. }
  2640. function naturalEarth1Raw(lambda, phi) {
  2641. var phi2 = phi * phi, phi4 = phi2 * phi2;
  2642. return [
  2643. lambda * (0.8707 - 0.131979 * phi2 + phi4 * (-0.013791 + phi4 * (0.003971 * phi2 - 0.001529 * phi4))),
  2644. phi * (1.007226 + phi2 * (0.015085 + phi4 * (-0.044475 + 0.028874 * phi2 - 0.005916 * phi4)))
  2645. ];
  2646. }
  2647. naturalEarth1Raw.invert = function(x, y) {
  2648. var phi = y, i = 25, delta;
  2649. do {
  2650. var phi2 = phi * phi, phi4 = phi2 * phi2;
  2651. phi -= delta = (phi * (1.007226 + phi2 * (0.015085 + phi4 * (-0.044475 + 0.028874 * phi2 - 0.005916 * phi4))) - y) /
  2652. (1.007226 + phi2 * (0.015085 * 3 + phi4 * (-0.044475 * 7 + 0.028874 * 9 * phi2 - 0.005916 * 11 * phi4)));
  2653. } while (abs(delta) > epsilon && --i > 0);
  2654. return [
  2655. x / (0.8707 + (phi2 = phi * phi) * (-0.131979 + phi2 * (-0.013791 + phi2 * phi2 * phi2 * (0.003971 - 0.001529 * phi2)))),
  2656. phi
  2657. ];
  2658. };
  2659. function naturalEarth1() {
  2660. return projection(naturalEarth1Raw)
  2661. .scale(175.295);
  2662. }
  2663. function orthographicRaw(x, y) {
  2664. return [cos(y) * sin(x), sin(y)];
  2665. }
  2666. orthographicRaw.invert = azimuthalInvert(asin);
  2667. function orthographic() {
  2668. return projection(orthographicRaw)
  2669. .scale(249.5)
  2670. .clipAngle(90 + epsilon);
  2671. }
  2672. function stereographicRaw(x, y) {
  2673. var cy = cos(y), k = 1 + cos(x) * cy;
  2674. return [cy * sin(x) / k, sin(y) / k];
  2675. }
  2676. stereographicRaw.invert = azimuthalInvert(function(z) {
  2677. return 2 * atan(z);
  2678. });
  2679. function stereographic() {
  2680. return projection(stereographicRaw)
  2681. .scale(250)
  2682. .clipAngle(142);
  2683. }
  2684. function transverseMercatorRaw(lambda, phi) {
  2685. return [log(tan((halfPi + phi) / 2)), -lambda];
  2686. }
  2687. transverseMercatorRaw.invert = function(x, y) {
  2688. return [-y, 2 * atan(exp(x)) - halfPi];
  2689. };
  2690. function transverseMercator() {
  2691. var m = mercatorProjection(transverseMercatorRaw),
  2692. center = m.center,
  2693. rotate = m.rotate;
  2694. m.center = function(_) {
  2695. return arguments.length ? center([-_[1], _[0]]) : (_ = center(), [_[1], -_[0]]);
  2696. };
  2697. m.rotate = function(_) {
  2698. return arguments.length ? rotate([_[0], _[1], _.length > 2 ? _[2] + 90 : 90]) : (_ = rotate(), [_[0], _[1], _[2] - 90]);
  2699. };
  2700. return rotate([0, 0, 90])
  2701. .scale(159.155);
  2702. }
  2703. exports.geoAlbers = albers;
  2704. exports.geoAlbersUsa = albersUsa;
  2705. exports.geoArea = area;
  2706. exports.geoAzimuthalEqualArea = azimuthalEqualArea;
  2707. exports.geoAzimuthalEqualAreaRaw = azimuthalEqualAreaRaw;
  2708. exports.geoAzimuthalEquidistant = azimuthalEquidistant;
  2709. exports.geoAzimuthalEquidistantRaw = azimuthalEquidistantRaw;
  2710. exports.geoBounds = bounds;
  2711. exports.geoCentroid = centroid;
  2712. exports.geoCircle = circle;
  2713. exports.geoClipAntimeridian = clipAntimeridian;
  2714. exports.geoClipCircle = clipCircle;
  2715. exports.geoClipExtent = extent;
  2716. exports.geoClipRectangle = clipRectangle;
  2717. exports.geoConicConformal = conicConformal;
  2718. exports.geoConicConformalRaw = conicConformalRaw;
  2719. exports.geoConicEqualArea = conicEqualArea;
  2720. exports.geoConicEqualAreaRaw = conicEqualAreaRaw;
  2721. exports.geoConicEquidistant = conicEquidistant;
  2722. exports.geoConicEquidistantRaw = conicEquidistantRaw;
  2723. exports.geoContains = contains;
  2724. exports.geoDistance = distance;
  2725. exports.geoEqualEarth = equalEarth;
  2726. exports.geoEqualEarthRaw = equalEarthRaw;
  2727. exports.geoEquirectangular = equirectangular;
  2728. exports.geoEquirectangularRaw = equirectangularRaw;
  2729. exports.geoGnomonic = gnomonic;
  2730. exports.geoGnomonicRaw = gnomonicRaw;
  2731. exports.geoGraticule = graticule;
  2732. exports.geoGraticule10 = graticule10;
  2733. exports.geoIdentity = identity;
  2734. exports.geoInterpolate = interpolate;
  2735. exports.geoLength = length;
  2736. exports.geoMercator = mercator;
  2737. exports.geoMercatorRaw = mercatorRaw;
  2738. exports.geoNaturalEarth1 = naturalEarth1;
  2739. exports.geoNaturalEarth1Raw = naturalEarth1Raw;
  2740. exports.geoOrthographic = orthographic;
  2741. exports.geoOrthographicRaw = orthographicRaw;
  2742. exports.geoPath = index;
  2743. exports.geoProjection = projection;
  2744. exports.geoProjectionMutator = projectionMutator;
  2745. exports.geoRotation = rotation;
  2746. exports.geoStereographic = stereographic;
  2747. exports.geoStereographicRaw = stereographicRaw;
  2748. exports.geoStream = geoStream;
  2749. exports.geoTransform = transform;
  2750. exports.geoTransverseMercator = transverseMercator;
  2751. exports.geoTransverseMercatorRaw = transverseMercatorRaw;
  2752. }));