d3-geo.js 87 KB

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