isobands.js 51 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883
  1. /* eslint no-console: ["error", { allow: ["log"] }] */
  2. /* eslint-env browser,node */
  3. import {isoBandOptions} from './options.js';
  4. import {cell2Polygons, traceBandPaths} from './polygons.js';
  5. import {QuadTree} from './quadtree.js';
  6. /*
  7. * lookup table to generate polygon paths or edges required to
  8. * trace the full polygon(s)
  9. */
  10. var shapeCoordinates = {
  11. square: function(cell, x0, x1, x2, x3, opt) {
  12. if (opt.polygons)
  13. cell.polygons.push([ [0,0], [0, 1], [1, 1], [1, 0] ]);
  14. },
  15. triangle_bl: function(cell, x0, x1, x2, x3, opt) {
  16. var bottomleft = opt.interpolate(x0, x1, opt.minV, opt.maxV);
  17. var leftbottom = opt.interpolate(x0, x3, opt.minV, opt.maxV);
  18. if (opt.polygons_full) {
  19. cell.edges.lb = {
  20. path: [ [0, leftbottom], [bottomleft, 0] ],
  21. move: {
  22. x: 0,
  23. y: -1,
  24. enter: 'tl'
  25. }
  26. };
  27. }
  28. if (opt.polygons)
  29. cell.polygons.push([ [0, leftbottom], [bottomleft, 0], [0, 0] ]);
  30. },
  31. triangle_br: function(cell, x0, x1, x2, x3, opt) {
  32. var bottomright = opt.interpolate(x0, x1, opt.minV, opt.maxV);
  33. var rightbottom = opt.interpolate(x1, x2, opt.minV, opt.maxV);
  34. if (opt.polygons_full) {
  35. cell.edges.br = {
  36. path: [ [bottomright, 0], [1, rightbottom] ],
  37. move: {
  38. x: 1,
  39. y: 0,
  40. enter: 'lb'
  41. }
  42. };
  43. }
  44. if (opt.polygons)
  45. cell.polygons.push([ [bottomright, 0], [1, rightbottom], [1, 0] ]);
  46. },
  47. triangle_tr: function(cell, x0, x1, x2, x3, opt) {
  48. var righttop = opt.interpolate(x1, x2, opt.minV, opt.maxV);
  49. var topright = opt.interpolate(x3, x2, opt.minV, opt.maxV);
  50. if (opt.polygons_full) {
  51. cell.edges.rt = {
  52. path: [ [1, righttop], [topright, 1] ],
  53. move: {
  54. x: 0,
  55. y: 1,
  56. enter: 'br'
  57. }
  58. };
  59. }
  60. if (opt.polygons)
  61. cell.polygons.push([ [1, righttop], [topright, 1], [1, 1] ]);
  62. },
  63. triangle_tl: function(cell, x0, x1, x2, x3, opt) {
  64. var topleft = opt.interpolate(x3, x2, opt.minV, opt.maxV);
  65. var lefttop = opt.interpolate(x0, x3, opt.minV, opt.maxV);
  66. if (opt.polygons_full) {
  67. cell.edges.tl = {
  68. path: [ [topleft, 1], [0, lefttop] ],
  69. move: {
  70. x: -1,
  71. y: 0,
  72. enter: 'rt'
  73. }
  74. };
  75. }
  76. if (opt.polygons)
  77. cell.polygons.push([ [0, lefttop], [0, 1], [topleft, 1] ]);
  78. },
  79. tetragon_t: function(cell, x0, x1, x2, x3, opt) {
  80. var righttop = opt.interpolate(x1, x2, opt.minV, opt.maxV);
  81. var lefttop = opt.interpolate(x0, x3, opt.minV, opt.maxV);
  82. if (opt.polygons_full) {
  83. cell.edges.rt = {
  84. path: [ [1, righttop], [0, lefttop] ],
  85. move: {
  86. x: -1,
  87. y: 0,
  88. enter: 'rt'
  89. }
  90. };
  91. }
  92. if (opt.polygons)
  93. cell.polygons.push([ [0, lefttop], [0, 1], [1, 1], [1, righttop] ]);
  94. },
  95. tetragon_r: function(cell, x0, x1, x2, x3, opt) {
  96. var bottomright = opt.interpolate(x0, x1, opt.minV, opt.maxV);
  97. var topright = opt.interpolate(x3, x2, opt.minV, opt.maxV);
  98. if (opt.polygons_full) {
  99. cell.edges.br = {
  100. path: [ [bottomright, 0], [topright, 1] ],
  101. move: {
  102. x: 0,
  103. y: 1,
  104. enter: 'br'
  105. }
  106. };
  107. }
  108. if (opt.polygons)
  109. cell.polygons.push([ [bottomright, 0], [topright, 1], [1, 1], [1, 0] ]);
  110. },
  111. tetragon_b: function(cell, x0, x1, x2, x3, opt) {
  112. var leftbottom = opt.interpolate(x0, x3, opt.minV, opt.maxV);
  113. var rightbottom = opt.interpolate(x1, x2, opt.minV, opt.maxV);
  114. if (opt.polygons_full) {
  115. cell.edges.lb = {
  116. path: [ [0, leftbottom], [1, rightbottom] ],
  117. move: {
  118. x: 1,
  119. y: 0,
  120. enter: 'lb'
  121. }
  122. };
  123. }
  124. if (opt.polygons)
  125. cell.polygons.push([ [0, 0], [0, leftbottom], [1, rightbottom], [1, 0] ]);
  126. },
  127. tetragon_l: function(cell, x0, x1, x2, x3, opt) {
  128. var topleft = opt.interpolate(x3, x2, opt.minV, opt.maxV);
  129. var bottomleft = opt.interpolate(x0, x1, opt.minV, opt.maxV);
  130. if (opt.polygons_full) {
  131. cell.edges.tl = {
  132. path: [ [topleft, 1], [bottomleft, 0] ],
  133. move: {
  134. x: 0,
  135. y: -1,
  136. enter: 'tl'
  137. }
  138. };
  139. }
  140. if (opt.polygons)
  141. cell.polygons.push([ [0, 0], [0, 1], [topleft, 1], [bottomleft, 0] ]);
  142. },
  143. tetragon_bl: function(cell, x0, x1, x2, x3, opt) {
  144. var bottomleft = opt.interpolate_a(x0, x1, opt.minV, opt.maxV);
  145. var bottomright = opt.interpolate_b(x0, x1, opt.minV, opt.maxV);
  146. var leftbottom = opt.interpolate_a(x0, x3, opt.minV, opt.maxV);
  147. var lefttop = opt.interpolate_b(x0, x3, opt.minV, opt.maxV);
  148. if (opt.polygons_full) {
  149. cell.edges.bl = {
  150. path: [ [bottomleft, 0], [0, leftbottom] ],
  151. move: {
  152. x: -1,
  153. y: 0,
  154. enter: 'rb'
  155. }
  156. };
  157. cell.edges.lt = {
  158. path: [ [0, lefttop], [bottomright, 0] ],
  159. move: {
  160. x: 0,
  161. y: -1,
  162. enter: 'tr'
  163. }
  164. };
  165. }
  166. if (opt.polygons)
  167. cell.polygons.push([ [bottomleft, 0], [0, leftbottom], [0, lefttop], [bottomright, 0] ]);
  168. },
  169. tetragon_br: function(cell, x0, x1, x2, x3, opt) {
  170. var bottomleft = opt.interpolate_a(x0, x1, opt.minV, opt.maxV);
  171. var bottomright = opt.interpolate_b(x0, x1, opt.minV, opt.maxV);
  172. var rightbottom = opt.interpolate_a(x1, x2, opt.minV, opt.maxV);
  173. var righttop = opt.interpolate_b(x1, x2, opt.minV, opt.maxV);
  174. if (opt.polygons_full) {
  175. cell.edges.bl = {
  176. path: [ [bottomleft, 0], [1, righttop] ],
  177. move: {
  178. x: 1,
  179. y: 0,
  180. enter: 'lt'
  181. }
  182. };
  183. cell.edges.rb = {
  184. path: [ [1, rightbottom], [bottomright, 0] ],
  185. move: {
  186. x: 0,
  187. y: -1,
  188. enter: 'tr'
  189. }
  190. };
  191. }
  192. if (opt.polygons)
  193. cell.polygons.push([ [bottomleft, 0], [1, righttop], [1, rightbottom], [bottomright, 0] ]);
  194. },
  195. tetragon_tr: function(cell, x0, x1, x2, x3, opt) {
  196. var topleft = opt.interpolate_a(x3, x2, opt.minV, opt.maxV);
  197. var topright = opt.interpolate_b(x3, x2, opt.minV, opt.maxV);
  198. var righttop = opt.interpolate_b(x1, x2, opt.minV, opt.maxV);
  199. var rightbottom = opt.interpolate_a(x1, x2, opt.minV, opt.maxV);
  200. if (opt.polygons_full) {
  201. cell.edges.rb = {
  202. path: [ [1, rightbottom], [topleft, 1] ],
  203. move: {
  204. x: 0,
  205. y: 1,
  206. enter: 'bl'
  207. }
  208. };
  209. cell.edges.tr = {
  210. path: [ [topright, 1], [1, righttop] ],
  211. move: {
  212. x: 1,
  213. y: 0,
  214. enter: 'lt'
  215. }
  216. };
  217. }
  218. if (opt.polygons)
  219. cell.polygons.push([ [1, rightbottom], [topleft, 1], [topright, 1], [1, righttop] ]);
  220. },
  221. tetragon_tl: function(cell, x0, x1, x2, x3, opt) {
  222. var topleft = opt.interpolate_a(x3, x2, opt.minV, opt.maxV);
  223. var topright = opt.interpolate_b(x3, x2, opt.minV, opt.maxV);
  224. var lefttop = opt.interpolate_b(x0, x3, opt.minV, opt.maxV);
  225. var leftbottom = opt.interpolate_a(x0, x3, opt.minV, opt.maxV);
  226. if (opt.polygons_full) {
  227. cell.edges.tr = {
  228. path: [ [topright, 1], [0, leftbottom] ],
  229. move: {
  230. x: -1,
  231. y: 0,
  232. enter: 'rb'
  233. }
  234. };
  235. cell.edges.lt = {
  236. path: [ [0, lefttop], [topleft, 1] ],
  237. move: {
  238. x: 0,
  239. y: 1,
  240. enter: 'bl'
  241. }
  242. };
  243. }
  244. if (opt.polygons)
  245. cell.polygons.push([ [topright, 1], [0, leftbottom], [0, lefttop], [topleft, 1] ]);
  246. },
  247. tetragon_lr: function(cell, x0, x1, x2, x3, opt) {
  248. var leftbottom = opt.interpolate_a(x0, x3, opt.minV, opt.maxV);
  249. var lefttop = opt.interpolate_b(x0, x3, opt.minV, opt.maxV);
  250. var righttop = opt.interpolate_b(x1, x2, opt.minV, opt.maxV);
  251. var rightbottom = opt.interpolate_a(x1, x2, opt.minV, opt.maxV);
  252. if (opt.polygons_full) {
  253. cell.edges.lt = {
  254. path: [ [0, lefttop], [1, righttop] ],
  255. move: {
  256. x: 1,
  257. y: 0,
  258. enter: 'lt'
  259. }
  260. };
  261. cell.edges.rb = {
  262. path: [ [1, rightbottom], [0, leftbottom] ],
  263. move: {
  264. x: -1,
  265. y: 0,
  266. enter: 'rb'
  267. }
  268. };
  269. }
  270. if (opt.polygons)
  271. cell.polygons.push([ [0, leftbottom], [0, lefttop], [1, righttop], [1, rightbottom] ]);
  272. },
  273. tetragon_tb: function(cell, x0, x1, x2, x3, opt) {
  274. var topleft = opt.interpolate_a(x3, x2, opt.minV, opt.maxV);
  275. var topright = opt.interpolate_b(x3, x2, opt.minV, opt.maxV);
  276. var bottomright = opt.interpolate_b(x0, x1, opt.minV, opt.maxV);
  277. var bottomleft = opt.interpolate_a(x0, x1, opt.minV, opt.maxV);
  278. if (opt.polygons_full) {
  279. cell.edges.tr = {
  280. path: [ [topright, 1], [bottomright, 0] ],
  281. move: {
  282. x: 0,
  283. y: -1,
  284. enter: 'tr'
  285. }
  286. };
  287. cell.edges.bl = {
  288. path: [ [bottomleft, 0], [topleft, 1] ],
  289. move: {
  290. x: 0,
  291. y: 1,
  292. enter: 'bl'
  293. }
  294. };
  295. }
  296. if (opt.polygons)
  297. cell.polygons.push([ [bottomleft, 0], [topleft, 1], [topright, 1], [bottomright, 0] ]);
  298. },
  299. pentagon_tr: function(cell, x0, x1, x2, x3, opt) {
  300. var topleft = opt.interpolate(x3, x2, opt.minV, opt.maxV);
  301. var rightbottom = opt.interpolate(x1, x2, opt.minV, opt.maxV);
  302. if (opt.polygons_full) {
  303. cell.edges.tl = {
  304. path: [[topleft, 1], [1, rightbottom]],
  305. move: {
  306. x: 1,
  307. y: 0,
  308. enter: 'lb'
  309. }
  310. };
  311. }
  312. if (opt.polygons)
  313. cell.polygons.push([ [0, 0], [0, 1], [topleft, 1], [1, rightbottom], [1, 0] ]);
  314. },
  315. pentagon_tl: function(cell, x0, x1, x2, x3, opt) {
  316. var leftbottom = opt.interpolate(x0, x3, opt.minV, opt.maxV);
  317. var topright = opt.interpolate(x3, x2, opt.minV, opt.maxV);
  318. if (opt.polygons_full) {
  319. cell.edges.lb = {
  320. path: [ [0, leftbottom], [topright, 1] ],
  321. move: {
  322. x: 0,
  323. y: 1,
  324. enter: 'br'
  325. }
  326. };
  327. }
  328. if (opt.polygons)
  329. cell.polygons.push([ [0, 0], [0, leftbottom], [topright, 1], [1, 1], [1, 0] ]);
  330. },
  331. pentagon_br: function(cell, x0, x1, x2, x3, opt) {
  332. var bottomleft = opt.interpolate(x0, x1, opt.minV, opt.maxV);
  333. var righttop = opt.interpolate(x1, x2, opt.minV, opt.maxV);
  334. if (opt.polygons_full) {
  335. cell.edges.rt = {
  336. path: [ [1, righttop], [bottomleft, 0] ],
  337. move: {
  338. x: 0,
  339. y: -1,
  340. enter: 'tl'
  341. }
  342. };
  343. }
  344. if (opt.polygons)
  345. cell.polygons.push([ [0, 0], [0, 1], [1, 1], [1, righttop], [bottomleft, 0] ]);
  346. },
  347. pentagon_bl: function(cell, x0, x1, x2, x3, opt) {
  348. var lefttop = opt.interpolate(x0, x3, opt.minV, opt.maxV);
  349. var bottomright = opt.interpolate(x0, x1, opt.minV, opt.maxV);
  350. if (opt.polygons_full) {
  351. cell.edges.br = {
  352. path: [ [bottomright, 0], [0, lefttop] ],
  353. move: {
  354. x: -1,
  355. y: 0,
  356. enter: 'rt'
  357. }
  358. };
  359. }
  360. if (opt.polygons)
  361. cell.polygons.push([ [0, lefttop], [0, 1], [1, 1], [1, 0], [bottomright, 0] ]);
  362. },
  363. pentagon_tr_rl: function(cell, x0, x1, x2, x3, opt) {
  364. var lefttop = opt.interpolate(x0, x3, opt.minV, opt.maxV);
  365. var topleft = opt.interpolate(x3, x2, opt.minV, opt.maxV);
  366. var righttop = opt.interpolate_b(x1, x2, opt.minV, opt.maxV);
  367. var rightbottom = opt.interpolate_a(x1, x2, opt.minV, opt.maxV);
  368. if (opt.polygons_full) {
  369. cell.edges.tl = {
  370. path: [ [topleft, 1], [1, righttop] ],
  371. move: {
  372. x: 1,
  373. y: 0,
  374. enter: 'lt'
  375. }
  376. };
  377. cell.edges.rb = {
  378. path: [ [1, rightbottom], [0, lefttop] ],
  379. move: {
  380. x: -1,
  381. y: 0,
  382. enter: 'rt'
  383. }
  384. };
  385. }
  386. if (opt.polygons)
  387. cell.polygons.push([ [0, lefttop], [0, 1], [topleft, 1], [1, righttop], [1, rightbottom] ]);
  388. },
  389. pentagon_rb_bt: function(cell, x0, x1, x2, x3, opt) {
  390. var righttop = opt.interpolate(x1, x2, opt.minV, opt.maxV);
  391. var bottomright = opt.interpolate_b(x0, x1, opt.minV, opt.maxV);
  392. var bottomleft = opt.interpolate_a(x0, x1, opt.minV, opt.maxV);
  393. var topright = opt.interpolate(x3, x2, opt.minV, opt.maxV);
  394. if (opt.polygons_full) {
  395. cell.edges.rt = {
  396. path: [ [1, righttop], [bottomright, 0] ],
  397. move: {
  398. x: 0,
  399. y: -1,
  400. enter: 'tr'
  401. }
  402. };
  403. cell.edges.bl = {
  404. path: [ [bottomleft, 0], [topright, 1] ],
  405. move: {
  406. x: 0,
  407. y: 1,
  408. enter: 'br'
  409. }
  410. };
  411. }
  412. if (opt.polygons)
  413. cell.polygons.push([ [topright, 1], [1, 1], [1, righttop], [bottomright, 0], [bottomleft, 0] ]);
  414. },
  415. pentagon_bl_lr: function(cell, x0, x1, x2, x3, opt) {
  416. var bottomright = opt.interpolate(x0, x1, opt.minV, opt.maxV);
  417. var leftbottom = opt.interpolate_a(x0, x3, opt.minV, opt.maxV);
  418. var lefttop = opt.interpolate_b(x0, x3, opt.minV, opt.maxV);
  419. var rightbottom = opt.interpolate(x1, x2, opt.minV, opt.maxV);
  420. if (opt.polygons_full) {
  421. cell.edges.br = {
  422. path: [ [bottomright, 0], [0, leftbottom] ],
  423. move: {
  424. x: -1,
  425. y: 0,
  426. enter: 'rb'
  427. }
  428. };
  429. cell.edges.lt = {
  430. path: [ [0, lefttop], [1, rightbottom] ],
  431. move: {
  432. x: 1,
  433. y: 0,
  434. enter: 'lb'
  435. }
  436. };
  437. }
  438. if (opt.polygons)
  439. cell.polygons.push([ [bottomright, 0], [0, leftbottom], [0, lefttop], [1, rightbottom], [1, 0] ]);
  440. },
  441. pentagon_lt_tb: function(cell, x0, x1, x2, x3, opt) {
  442. var leftbottom = opt.interpolate(x0, x3, opt.minV, opt.maxV);
  443. var topleft = opt.interpolate_a(x3, x2, opt.minV, opt.maxV);
  444. var topright = opt.interpolate_b(x3, x2, opt.minV, opt.maxV);
  445. var bottomleft = opt.interpolate(x0, x1, opt.minV, opt.maxV);
  446. if (opt.polygons_full) {
  447. cell.edges.lb = {
  448. path: [ [0, leftbottom], [topleft, 1] ],
  449. move: {
  450. x: 0,
  451. y: 1,
  452. enter: 'bl'
  453. }
  454. };
  455. cell.edges.tr = {
  456. path: [ [topright, 1], [bottomleft, 0] ],
  457. move: {
  458. x: 0,
  459. y: -1,
  460. enter: 'tl'
  461. }
  462. };
  463. }
  464. if (opt.polygons)
  465. cell.polygons.push([ [0, 0], [0, leftbottom], [topleft, 1], [topright, 1], [bottomleft, 0] ]);
  466. },
  467. pentagon_bl_tb: function(cell, x0, x1, x2, x3, opt) {
  468. var lefttop = opt.interpolate(x0, x3, opt.minV, opt.maxV);
  469. var topleft = opt.interpolate(x3, x2, opt.minV, opt.maxV);
  470. var bottomright = opt.interpolate_b(x0, x1, opt.minV, opt.maxV);
  471. var bottomleft = opt.interpolate_a(x0, x1, opt.minV, opt.maxV);
  472. if (opt.polygons_full) {
  473. cell.edges.bl = {
  474. path: [ [bottomleft, 0], [0, lefttop] ],
  475. move: {
  476. x: -1,
  477. y: 0,
  478. enter: 'rt'
  479. }
  480. };
  481. cell.edges.tl = {
  482. path: [ [ topleft, 1], [bottomright, 0] ],
  483. move: {
  484. x: 0,
  485. y: -1,
  486. enter: 'tr'
  487. }
  488. };
  489. }
  490. if (opt.polygons)
  491. cell.polygons.push([ [0, lefttop], [0, 1], [topleft, 1], [bottomright, 0], [bottomleft, 0] ]);
  492. },
  493. pentagon_lt_rl: function(cell, x0, x1, x2, x3, opt) {
  494. var leftbottom = opt.interpolate_a(x0, x3, opt.minV, opt.maxV);
  495. var lefttop = opt.interpolate_b(x0, x3, opt.minV, opt.maxV);
  496. var topright = opt.interpolate(x3, x2, opt.minV, opt.maxV);
  497. var righttop = opt.interpolate(x1, x3, opt.minV, opt.maxV);
  498. if (opt.polygons_full) {
  499. cell.edges.lt = {
  500. path: [ [0, lefttop], [topright, 1] ],
  501. move: {
  502. x: 0,
  503. y: 1,
  504. enter: 'br'
  505. }
  506. };
  507. cell.edges.rt = {
  508. path: [ [1, righttop], [0, leftbottom] ],
  509. move: {
  510. x: -1,
  511. y: 0,
  512. enter: 'rb'
  513. }
  514. };
  515. }
  516. if (opt.polygons)
  517. cell.polygons.push([ [0, leftbottom], [0, lefttop], [topright, 1], [1, 1], [1, righttop] ]);
  518. },
  519. pentagon_tr_bt: function(cell, x0, x1, x2, x3, opt) {
  520. var topleft = opt.interpolate_a(x3, x2, opt.minV, opt.maxV);
  521. var topright = opt.interpolate_b(x3, x2, opt.minV, opt.maxV);
  522. var rightbottom = opt.interpolate(x1, x2, opt.minV, opt.maxV);
  523. var bottomright = opt.interpolate(x0, x1, opt.minV, opt.maxV);
  524. if (opt.polygons_full) {
  525. cell.edges.br = {
  526. path: [ [bottomright, 0], [topleft, 1] ],
  527. move: {
  528. x: 0,
  529. y: 1,
  530. enter: 'bl'
  531. }
  532. };
  533. cell.edges.tr = {
  534. path: [ [topright, 1], [1, rightbottom] ],
  535. move: {
  536. x: 1,
  537. y: 0,
  538. enter: 'lb'
  539. }
  540. };
  541. }
  542. if (opt.polygons)
  543. cell.polygons.push([ [topleft, 1], [topright, 1], [1, rightbottom], [1, 0], [bottomright, 0] ]);
  544. },
  545. pentagon_rb_lr: function(cell, x0, x1, x2, x3, opt) {
  546. var leftbottom = opt.interpolate(x0, x3, opt.minV, opt.maxV);
  547. var righttop = opt.interpolate_b(x1, x2, opt.minV, opt.maxV);
  548. var rightbottom = opt.interpolate_a(x1, x2, opt.minV, opt.maxV);
  549. var bottomleft = opt.interpolate(x0, x1, opt.minV, opt.maxV);
  550. if (opt.polygons_full) {
  551. cell.edges.lb = {
  552. path: [ [0, leftbottom], [1, righttop] ],
  553. move: {
  554. x: 1,
  555. y: 0,
  556. enter: 'lt'
  557. }
  558. };
  559. cell.edges.rb = {
  560. path: [ [1, rightbottom], [bottomleft, 0] ],
  561. move: {
  562. x: 0,
  563. y: -1,
  564. enter: 'tl'
  565. }
  566. };
  567. }
  568. if (opt.polygons)
  569. cell.polygons.push([ [0, 0], [0, leftbottom], [1, righttop], [1, rightbottom], [bottomleft, 0] ]);
  570. },
  571. hexagon_lt_tr: function(cell, x0, x1, x2, x3, opt) {
  572. var leftbottom = opt.interpolate(x0, x3, opt.minV, opt.maxV);
  573. var topleft = opt.interpolate_a(x3, x2, opt.minV, opt.maxV);
  574. var topright = opt.interpolate_b(x3, x2, opt.minV, opt.maxV);
  575. var rightbottom = opt.interpolate(x1, x2, opt.minV, opt.maxV);
  576. if (opt.polygons_full) {
  577. cell.edges.lb = {
  578. path: [ [0, leftbottom], [topleft, 1] ],
  579. move: {
  580. x: 0,
  581. y: 1,
  582. enter: 'bl'
  583. }
  584. };
  585. cell.edges.tr = {
  586. path: [ [topright, 1], [1, rightbottom] ],
  587. move: {
  588. x: 1,
  589. y: 0,
  590. enter: 'lb'
  591. }
  592. };
  593. }
  594. if (opt.polygons)
  595. cell.polygons.push([ [0, 0], [0, leftbottom], [topleft, 1], [topright, 1], [1, rightbottom], [1, 0] ]);
  596. },
  597. hexagon_bl_lt: function(cell, x0, x1, x2, x3, opt) {
  598. var bottomright = opt.interpolate(x0, x1, opt.minV, opt.maxV);
  599. var leftbottom = opt.interpolate_a(x0, x3, opt.minV, opt.maxV);
  600. var lefttop = opt.interpolate_b(x0, x3, opt.minV, opt.maxV);
  601. var topright = opt.interpolate(x3, x2, opt.minV, opt.maxV);
  602. if (opt.polygons_full) {
  603. cell.edges.br = {
  604. path: [ [bottomright, 0], [0, leftbottom] ],
  605. move: {
  606. x: -1,
  607. y: 0,
  608. enter: 'rb'
  609. }
  610. };
  611. cell.edges.lt = {
  612. path: [ [0, lefttop], [topright, 1] ],
  613. move: {
  614. x: 0,
  615. y: 1,
  616. enter: 'br'
  617. }
  618. };
  619. }
  620. if (opt.polygons)
  621. cell.polygons.push([ [bottomright, 0], [0, leftbottom], [0, lefttop], [topright, 1], [1, 1], [1, 0] ]);
  622. },
  623. hexagon_bl_rb: function(cell, x0, x1, x2, x3, opt) {
  624. var bottomleft = opt.interpolate_a(x0, x1, opt.minV, opt.maxV);
  625. var bottomright = opt.interpolate_b(x0, x1, opt.minV, opt.maxV);
  626. var lefttop = opt.interpolate(x0, x3, opt.minV, opt.maxV);
  627. var righttop = opt.interpolate(x1, x2, opt.minV, opt.maxV);
  628. if (opt.polygons_full) {
  629. cell.edges.bl = {
  630. path: [ [bottomleft, 0], [0, lefttop] ],
  631. move: {
  632. x: -1,
  633. y: 0,
  634. enter: 'rt'
  635. }
  636. };
  637. cell.edges.rt = {
  638. path: [ [1, righttop], [bottomright, 0] ],
  639. move: {
  640. x: 0,
  641. y: -1,
  642. enter: 'tr'
  643. }
  644. };
  645. }
  646. if (opt.polygons)
  647. cell.polygons.push([ [bottomleft, 0], [0, lefttop], [0, 1], [1, 1], [1, righttop], [bottomright, 0] ]);
  648. },
  649. hexagon_tr_rb: function(cell, x0, x1, x2, x3, opt) {
  650. var bottomleft = opt.interpolate(x0, x1, opt.minV, opt.maxV);
  651. var topleft = opt.interpolate(x3, x2, opt.minV, opt.maxV);
  652. var righttop = opt.interpolate_b(x1, x2, opt.minV, opt.maxV);
  653. var rightbottom = opt.interpolate_a(x1, x2, opt.minV, opt.maxV);
  654. if (opt.polygons_full) {
  655. cell.edges.tl = {
  656. path: [ [topleft, 1], [1, righttop] ],
  657. move: {
  658. x: 1,
  659. y: 0,
  660. enter: 'lt'
  661. }
  662. };
  663. cell.edges.rb = {
  664. path: [ [1, rightbottom], [bottomleft, 0] ],
  665. move: {
  666. x: 0,
  667. y: -1,
  668. enter: 'tl'
  669. }
  670. };
  671. }
  672. if (opt.polygons)
  673. cell.polygons.push([ [0, 0], [0, 1], [topleft, 1], [1, righttop], [1, rightbottom], [bottomleft, 0] ]);
  674. },
  675. hexagon_lt_rb: function(cell, x0, x1, x2, x3, opt) {
  676. var leftbottom = opt.interpolate(x0, x3, opt.minV, opt.maxV);
  677. var topright = opt.interpolate(x3, x2, opt.minV, opt.maxV);
  678. var righttop = opt.interpolate(x1, x2, opt.minV, opt.maxV);
  679. var bottomleft = opt.interpolate(x0, x1, opt.minV, opt.maxV);
  680. if (opt.polygons_full) {
  681. cell.edges.lb = {
  682. path: [ [0, leftbottom], [topright, 1] ],
  683. move: {
  684. x: 0,
  685. y: 1,
  686. enter: 'br'
  687. }
  688. };
  689. cell.edges.rt = {
  690. path: [ [1, righttop], [bottomleft, 0] ],
  691. move: {
  692. x: 0,
  693. y: -1,
  694. enter: 'tl'
  695. }
  696. };
  697. }
  698. if (opt.polygons)
  699. cell.polygons.push([ [0, 0], [0, leftbottom], [topright, 1], [1, 1], [1, righttop], [bottomleft, 0] ]);
  700. },
  701. hexagon_bl_tr: function(cell, x0, x1, x2, x3, opt) {
  702. var bottomright = opt.interpolate(x0, x1, opt.minV, opt.maxV);
  703. var lefttop = opt.interpolate(x0, x3, opt.minV, opt.maxV);
  704. var topleft = opt.interpolate(x3, x2, opt.minV, opt.maxV);
  705. var rightbottom = opt.interpolate(x1, x2, opt.minV, opt.maxV);
  706. if (opt.polygons_full) {
  707. cell.edges.br = {
  708. path: [ [bottomright, 0], [0, lefttop] ],
  709. move: {
  710. x: -1,
  711. y: 0,
  712. enter: 'rt'
  713. }
  714. };
  715. cell.edges.tl = {
  716. path: [ [topleft, 1], [1, rightbottom] ],
  717. move: {
  718. x: 1,
  719. y: 0,
  720. enter: 'lb'
  721. }
  722. };
  723. }
  724. if (opt.polygons)
  725. cell.polygons.push([ [bottomright, 0], [0, lefttop], [0, 1], [topleft, 1], [1, rightbottom], [1, 0] ]);
  726. },
  727. heptagon_tr: function(cell, x0, x1, x2, x3, opt) {
  728. var bottomleft = opt.interpolate_a(x0, x1, opt.minV, opt.maxV);
  729. var bottomright = opt.interpolate_b(x0, x1, opt.minV, opt.maxV);
  730. var leftbottom = opt.interpolate_a(x0, x3, opt.minV, opt.maxV);
  731. var lefttop = opt.interpolate_b(x0, x3, opt.minV, opt.maxV);
  732. var topright = opt.interpolate(x3, x2, opt.minV, opt.maxV);
  733. var righttop = opt.interpolate(x1, x2, opt.minV, opt.maxV);
  734. if (opt.polygons_full) {
  735. cell.edges.bl = {
  736. path: [ [bottomleft, 0], [0, leftbottom] ],
  737. move: {
  738. x: -1,
  739. y: 0,
  740. enter: 'rb'
  741. }
  742. };
  743. cell.edges.lt = {
  744. path: [ [0, lefttop], [topright, 1] ],
  745. move: {
  746. x: 0,
  747. y: 1,
  748. enter: 'br'
  749. }
  750. };
  751. cell.edges.rt = {
  752. path: [ [1, righttop], [bottomright, 0] ],
  753. move: {
  754. x: 0,
  755. y: -1,
  756. enter: 'tr'
  757. }
  758. };
  759. }
  760. if (opt.polygons)
  761. cell.polygons.push([ [bottomleft, 0], [0, leftbottom], [0, lefttop], [topright, 1], [1, 1], [1, righttop], [bottomright, 0] ]);
  762. },
  763. heptagon_bl: function(cell, x0, x1, x2, x3, opt) {
  764. var bottomleft = opt.interpolate(x0, x1, opt.minV, opt.maxV);
  765. var leftbottom = opt.interpolate(x0, x3, opt.minV, opt.maxV);
  766. var topleft = opt.interpolate_a(x3, x2, opt.minV, opt.maxV);
  767. var topright = opt.interpolate_b(x3, x2, opt.minV, opt.maxV);
  768. var righttop = opt.interpolate_b(x1, x2, opt.minV, opt.maxV);
  769. var rightbottom = opt.interpolate_a(x1, x2, opt.minV, opt.maxV);
  770. if (opt.polygons_full) {
  771. cell.edges.lb = {
  772. path: [ [0, leftbottom], [topleft, 1] ],
  773. move: {
  774. x: 0,
  775. y: 1,
  776. enter: 'bl'
  777. }
  778. };
  779. cell.edges.tr = {
  780. path: [ [topright, 1], [1, righttop] ],
  781. move: {
  782. x: 1,
  783. y: 0,
  784. enter: 'lt'
  785. }
  786. };
  787. cell.edges.rb = {
  788. path: [ [1, rightbottom], [bottomleft, 0] ],
  789. move: {
  790. x: 0,
  791. y: -1,
  792. enter: 'tl'
  793. }
  794. };
  795. }
  796. if (opt.polygons)
  797. cell.polygons.push([ [0, 0], [0, leftbottom], [topleft, 1], [topright, 1], [1, righttop], [1, rightbottom], [bottomleft, 0] ]);
  798. },
  799. heptagon_tl: function(cell, x0, x1, x2, x3, opt) {
  800. var bottomleft = opt.interpolate_a(x0, x1, opt.minV, opt.maxV);
  801. var bottomright = opt.interpolate_b(x0, x1, opt.minV, opt.maxV);
  802. var lefttop = opt.interpolate(x0, x3, opt.minV, opt.maxV);
  803. var topleft = opt.interpolate(x3, x2, opt.minV, opt.maxV);
  804. var righttop = opt.interpolate_b(x1, x2, opt.minV, opt.maxV);
  805. var rightbottom = opt.interpolate_a(x1, x2, opt.minV, opt.maxV);
  806. if (opt.polygons_full) {
  807. cell.edges.bl = {
  808. path: [ [bottomleft, 0], [0, lefttop] ],
  809. move: {
  810. x: -1,
  811. y: 0,
  812. enter: 'rt'
  813. }
  814. };
  815. cell.edges.tl = {
  816. path: [ [topleft, 1], [1, righttop] ],
  817. move: {
  818. x: 1,
  819. y: 0,
  820. enter: 'lt'
  821. }
  822. };
  823. cell.edges.rb = {
  824. path: [ [1, rightbottom], [bottomright, 0] ],
  825. move: {
  826. x: 0,
  827. y: -1,
  828. enter: 'tr'
  829. }
  830. };
  831. }
  832. if (opt.polygons)
  833. cell.polygons.push([ [bottomleft, 0], [0, lefttop], [0, 1], [topleft, 1], [1, righttop], [1, rightbottom], [bottomright, 0] ]);
  834. },
  835. heptagon_br: function(cell, x0, x1, x2, x3, opt) {
  836. var bottomright = opt.interpolate(x0, x1, opt.minV, opt.maxV);
  837. var leftbottom = opt.interpolate_a(x0, x3, opt.minV, opt.maxV);
  838. var lefttop = opt.interpolate_b(x0, x3, opt.minV, opt.maxV);
  839. var topleft = opt.interpolate_a(x3, x2, opt.minV, opt.maxV);
  840. var topright = opt.interpolate_b(x3, x2, opt.minV, opt.maxV);
  841. var rightbottom = opt.interpolate(x1, x2, opt.minV, opt.maxV);
  842. if (opt.polygons_full) {
  843. cell.edges.br = {
  844. path: [ [bottomright, 0], [0, leftbottom] ],
  845. move: {
  846. x: -1,
  847. y: 0,
  848. enter: 'rb'
  849. }
  850. };
  851. cell.edges.lt = {
  852. path: [ [0, lefttop], [topleft, 1] ],
  853. move: {
  854. x: 0,
  855. y: 1,
  856. enter: 'bl'
  857. }
  858. };
  859. cell.edges.tr = {
  860. path: [ [topright, 1], [1, rightbottom] ],
  861. move: {
  862. x: 1,
  863. y: 0,
  864. enter: 'lb'
  865. }
  866. };
  867. }
  868. if (opt.polygons)
  869. cell.polygons.push([ [bottomright,0], [0, leftbottom], [0, lefttop], [topleft, 1], [topright, 1], [1, rightbottom], [1, 0] ]);
  870. },
  871. octagon: function(cell, x0, x1, x2, x3, opt) {
  872. var bottomleft = opt.interpolate_a(x0, x1, opt.minV, opt.maxV);
  873. var bottomright = opt.interpolate_b(x0, x1, opt.minV, opt.maxV);
  874. var leftbottom = opt.interpolate_a(x0, x3, opt.minV, opt.maxV);
  875. var lefttop = opt.interpolate_b(x0, x3, opt.minV, opt.maxV);
  876. var topleft = opt.interpolate_a(x3, x2, opt.minV, opt.maxV);
  877. var topright = opt.interpolate_b(x3, x2, opt.minV, opt.maxV);
  878. var righttop = opt.interpolate_b(x1, x2, opt.minV, opt.maxV);
  879. var rightbottom = opt.interpolate_a(x1, x2, opt.minV, opt.maxV);
  880. if (opt.polygons_full) {
  881. cell.edges.bl = {
  882. path: [ [bottomleft, 0], [0, leftbottom] ],
  883. move: {
  884. x: -1,
  885. y: 0,
  886. enter: 'rb'
  887. }
  888. };
  889. cell.edges.lt = {
  890. path: [ [0, lefttop], [topleft, 1] ],
  891. move: {
  892. x: 0,
  893. y: 1,
  894. enter: 'bl'
  895. }
  896. };
  897. cell.edges.tr = {
  898. path: [ [topright, 1], [1, righttop] ],
  899. move: {
  900. x: 1,
  901. y: 0,
  902. enter: 'lt'
  903. }
  904. };
  905. cell.edges.rb = {
  906. path: [ [1, rightbottom], [bottomright, 0] ],
  907. move: {
  908. x: 0,
  909. y: -1,
  910. enter: 'tr'
  911. }
  912. };
  913. }
  914. if (opt.polygons)
  915. cell.polygons.push([ [bottomleft, 0], [0, leftbottom], [0, lefttop], [topleft, 1], [topright, 1], [1, righttop], [1, rightbottom], [bottomright, 0] ]);
  916. }
  917. };
  918. /*
  919. * Compute isobands(s) for a scalar 2D field given a certain
  920. * threshold and a bandwidth by applying the Marching Squares
  921. * Algorithm. The function returns a list of path coordinates
  922. * either for individual polygons within each grid cell, or the
  923. * outline of connected polygons.
  924. */
  925. function isoBands(input, minV, bandWidth, options) {
  926. var i,
  927. j,
  928. settings,
  929. useQuadTree = false,
  930. tree = null,
  931. root = null,
  932. data = null,
  933. cellGrid = null,
  934. multiBand = false,
  935. bw = [],
  936. bandPolygons = [],
  937. ret = [];
  938. /* basic input validation */
  939. if (!input) throw new Error('data is required');
  940. if (minV === undefined || minV === null) throw new Error('lowerBound is required');
  941. if (bandWidth === undefined || bandWidth === null) throw new Error('bandWidth is required');
  942. if ((!!options) && (typeof options !== 'object')) throw new Error('options must be an object');
  943. settings = isoBandOptions(options);
  944. /* check for input data */
  945. if (input instanceof QuadTree) {
  946. tree = input;
  947. root = input.root;
  948. data = input.data;
  949. if (!settings.noQuadTree)
  950. useQuadTree = true;
  951. } else if (Array.isArray(input) && Array.isArray(input[0])) {
  952. data = input;
  953. } else {
  954. throw new Error('input is neither array of arrays nor object retrieved from \'QuadTree()\'');
  955. }
  956. /* check and prepare input thresholds */
  957. if (Array.isArray(minV)) {
  958. multiBand = true;
  959. /* activate QuadTree optimization if not explicitly forbidden by user settings */
  960. if (!settings.noQuadTree)
  961. useQuadTree = true;
  962. /* check if all minV are numbers */
  963. for (i = 0; i < minV.length; i++)
  964. if (isNaN(+minV[i]))
  965. throw new Error('lowerBound[' + i + '] is not a number');
  966. if (Array.isArray(bandWidth)) {
  967. if (minV.length !== bandWidth.length)
  968. throw new Error('lowerBound and bandWidth have unequal lengths');
  969. /* check bandwidth values */
  970. for (i = 0; i < bandWidth.length; i++)
  971. if (isNaN(+bandWidth[i]))
  972. throw new Error('bandWidth[' + i + '] is not a number');
  973. } else {
  974. if (isNaN(+bandWidth))
  975. throw new Error('bandWidth must be a number');
  976. bw = [];
  977. for (i = 0; i < minV.length; i++) {
  978. bw.push(bandWidth);
  979. }
  980. bandWidth = bw;
  981. }
  982. } else {
  983. if (isNaN(+minV))
  984. throw new Error('lowerBound must be a number');
  985. minV = [ minV ];
  986. if (isNaN(+bandWidth))
  987. throw new Error('bandWidth must be a number');
  988. bandWidth = [ bandWidth ];
  989. }
  990. /* create QuadTree root node if not already present */
  991. if ((useQuadTree) && (!root)) {
  992. tree = new QuadTree(data);
  993. root = tree.root;
  994. data = tree.data;
  995. }
  996. if (settings.verbose) {
  997. if(settings.polygons)
  998. console.log('MarchingSquaresJS-isoBands: returning single polygons for each grid cell');
  999. else
  1000. console.log('MarchingSquaresJS-isoBands: returning polygon paths for entire data grid');
  1001. if (multiBand)
  1002. console.log('MarchingSquaresJS-isoBands: multiple bands requested, returning array of band polygons instead of polygons for a single band');
  1003. }
  1004. /* Done with all input validation, now let's start computing stuff */
  1005. /* loop over all minV values */
  1006. minV.forEach(function(lowerBound, b) {
  1007. bandPolygons = [];
  1008. /* store bounds for current computation in settings object */
  1009. settings.minV = lowerBound;
  1010. settings.maxV = lowerBound + bandWidth[b];
  1011. if(settings.verbose)
  1012. console.log('MarchingSquaresJS-isoBands: computing isobands for [' + lowerBound + ':' + (lowerBound + bandWidth[b]) + ']');
  1013. if (settings.polygons) {
  1014. /* compose list of polygons for each single cell */
  1015. if (useQuadTree) {
  1016. /* go through list of cells retrieved from QuadTree */
  1017. root
  1018. .cellsInBand(settings.minV, settings.maxV, true)
  1019. .forEach(function(c) {
  1020. bandPolygons = bandPolygons.concat(
  1021. cell2Polygons(
  1022. prepareCell(data,
  1023. c.x,
  1024. c.y,
  1025. settings),
  1026. c.x,
  1027. c.y,
  1028. settings
  1029. ));
  1030. });
  1031. } else {
  1032. /* go through entire array of input data */
  1033. for (j = 0; j < data.length - 1; ++j) {
  1034. for (i = 0; i < data[0].length - 1; ++i)
  1035. bandPolygons = bandPolygons.concat(
  1036. cell2Polygons(
  1037. prepareCell(data,
  1038. i,
  1039. j,
  1040. settings),
  1041. i,
  1042. j,
  1043. settings
  1044. ));
  1045. }
  1046. }
  1047. } else {
  1048. /* sparse grid of input data cells */
  1049. cellGrid = [];
  1050. for (i = 0; i < data[0].length - 1; ++i)
  1051. cellGrid[i] = [];
  1052. /* compose list of polygons for entire input grid */
  1053. if (useQuadTree) {
  1054. /* collect the cells */
  1055. root
  1056. .cellsInBand(settings.minV, settings.maxV, false)
  1057. .forEach(function(c) {
  1058. cellGrid[c.x][c.y] = prepareCell(data,
  1059. c.x,
  1060. c.y,
  1061. settings);
  1062. });
  1063. } else {
  1064. /* prepare cells */
  1065. for (i = 0; i < data[0].length - 1; ++i) {
  1066. for (j = 0; j < data.length - 1; ++j) {
  1067. cellGrid[i][j] = prepareCell(data,
  1068. i,
  1069. j,
  1070. settings);
  1071. }
  1072. }
  1073. }
  1074. bandPolygons = traceBandPaths(data, cellGrid, settings);
  1075. }
  1076. /* finally, add polygons to output array */
  1077. if (multiBand)
  1078. ret.push(bandPolygons);
  1079. else
  1080. ret = bandPolygons;
  1081. if(typeof settings.successCallback === 'function')
  1082. settings.successCallback(ret, lowerBound, bandWidth[b]);
  1083. });
  1084. return ret;
  1085. }
  1086. /*
  1087. * Thats all for the public interface, below follows the actual
  1088. * implementation
  1089. */
  1090. /*
  1091. * For isoBands, each square is defined by the three states
  1092. * of its corner points. However, since computers use power-2
  1093. * values, we use 2bits per trit, i.e.:
  1094. *
  1095. * 00 ... below minV
  1096. * 01 ... between minV and maxV
  1097. * 10 ... above maxV
  1098. *
  1099. * Hence we map the 4-trit configurations as follows:
  1100. *
  1101. * 0000 => 0
  1102. * 0001 => 1
  1103. * 0002 => 2
  1104. * 0010 => 4
  1105. * 0011 => 5
  1106. * 0012 => 6
  1107. * 0020 => 8
  1108. * 0021 => 9
  1109. * 0022 => 10
  1110. * 0100 => 16
  1111. * 0101 => 17
  1112. * 0102 => 18
  1113. * 0110 => 20
  1114. * 0111 => 21
  1115. * 0112 => 22
  1116. * 0120 => 24
  1117. * 0121 => 25
  1118. * 0122 => 26
  1119. * 0200 => 32
  1120. * 0201 => 33
  1121. * 0202 => 34
  1122. * 0210 => 36
  1123. * 0211 => 37
  1124. * 0212 => 38
  1125. * 0220 => 40
  1126. * 0221 => 41
  1127. * 0222 => 42
  1128. * 1000 => 64
  1129. * 1001 => 65
  1130. * 1002 => 66
  1131. * 1010 => 68
  1132. * 1011 => 69
  1133. * 1012 => 70
  1134. * 1020 => 72
  1135. * 1021 => 73
  1136. * 1022 => 74
  1137. * 1100 => 80
  1138. * 1101 => 81
  1139. * 1102 => 82
  1140. * 1110 => 84
  1141. * 1111 => 85
  1142. * 1112 => 86
  1143. * 1120 => 88
  1144. * 1121 => 89
  1145. * 1122 => 90
  1146. * 1200 => 96
  1147. * 1201 => 97
  1148. * 1202 => 98
  1149. * 1210 => 100
  1150. * 1211 => 101
  1151. * 1212 => 102
  1152. * 1220 => 104
  1153. * 1221 => 105
  1154. * 1222 => 106
  1155. * 2000 => 128
  1156. * 2001 => 129
  1157. * 2002 => 130
  1158. * 2010 => 132
  1159. * 2011 => 133
  1160. * 2012 => 134
  1161. * 2020 => 136
  1162. * 2021 => 137
  1163. * 2022 => 138
  1164. * 2100 => 144
  1165. * 2101 => 145
  1166. * 2102 => 146
  1167. * 2110 => 148
  1168. * 2111 => 149
  1169. * 2112 => 150
  1170. * 2120 => 152
  1171. * 2121 => 153
  1172. * 2122 => 154
  1173. * 2200 => 160
  1174. * 2201 => 161
  1175. * 2202 => 162
  1176. * 2210 => 164
  1177. * 2211 => 165
  1178. * 2212 => 166
  1179. * 2220 => 168
  1180. * 2221 => 169
  1181. * 2222 => 170
  1182. */
  1183. /*
  1184. * ####################################
  1185. * Some small helper functions
  1186. * ####################################
  1187. */
  1188. function computeCenterAverage(bl, br, tr, tl, minV, maxV) {
  1189. var average = (tl + tr + br + bl) / 4;
  1190. if (average > maxV)
  1191. return 2; /* above isoband limits */
  1192. if (average < minV)
  1193. return 0; /* below isoband limits */
  1194. return 1; /* within isoband limits */
  1195. }
  1196. function prepareCell(grid, x, y, opt) {
  1197. var cell,
  1198. center_avg;
  1199. /* compose the 4-trit corner representation */
  1200. var cval = 0;
  1201. var x3 = grid[y + 1][x];
  1202. var x2 = grid[y + 1][x + 1];
  1203. var x1 = grid[y][x + 1];
  1204. var x0 = grid[y][x];
  1205. var minV = opt.minV;
  1206. var maxV = opt.maxV;
  1207. /*
  1208. * Note that missing data within the grid will result
  1209. * in horribly failing to trace full polygon paths
  1210. */
  1211. if(isNaN(x0) || isNaN(x1) || isNaN(x2) || isNaN(x3)) {
  1212. return;
  1213. }
  1214. /*
  1215. * Here we detect the type of the cell
  1216. *
  1217. * x3 ---- x2
  1218. * | |
  1219. * | |
  1220. * x0 ---- x1
  1221. *
  1222. * with edge points
  1223. *
  1224. * x0 = (x,y),
  1225. * x1 = (x + 1, y),
  1226. * x2 = (x + 1, y + 1), and
  1227. * x3 = (x, y + 1)
  1228. *
  1229. * and compute the polygon intersections with the edges
  1230. * of the cell. Each edge value may be (i) below, (ii) within,
  1231. * or (iii) above the values of the isoband limits. We
  1232. * encode this property using 2 bits of information, where
  1233. *
  1234. * 00 ... below,
  1235. * 01 ... within, and
  1236. * 10 ... above
  1237. *
  1238. * Then we store the cells value as vector
  1239. *
  1240. * cval = (x0, x1, x2, x3)
  1241. *
  1242. * where x0 are the two least significant bits (0th, 1st),
  1243. * x1 the 2nd and 3rd bit, and so on. This essentially
  1244. * enables us to work with a single integer number
  1245. */
  1246. cval |= (x3 < minV) ? 0 : (x3 > maxV) ? 128 : 64;
  1247. cval |= (x2 < minV) ? 0 : (x2 > maxV) ? 32 : 16;
  1248. cval |= (x1 < minV) ? 0 : (x1 > maxV) ? 8 : 4;
  1249. cval |= (x0 < minV) ? 0 : (x0 > maxV) ? 2 : 1;
  1250. /* make sure cval is a number */
  1251. cval = +cval;
  1252. /*
  1253. * cell center average trit for ambiguous cases, where
  1254. * 0 ... below iso band
  1255. * 1 ... within iso band
  1256. * 2 ... above isoband
  1257. */
  1258. center_avg = 0;
  1259. cell = {
  1260. cval: cval,
  1261. polygons: [],
  1262. edges: {},
  1263. x0: x0,
  1264. x1: x1,
  1265. x2: x2,
  1266. x3: x3,
  1267. x: x,
  1268. y: y
  1269. };
  1270. /*
  1271. * Compute interpolated intersections of the polygon(s)
  1272. * with the cell borders and (i) add edges for polygon
  1273. * trace-back, or (ii) a list of small closed polygons
  1274. * according to look-up table
  1275. */
  1276. switch (cval) {
  1277. case 85: /* 1111 */
  1278. shapeCoordinates.square(cell, x0, x1, x2, x3, opt);
  1279. /* fall through */
  1280. case 0: /* 0000 */
  1281. /* fall through */
  1282. case 170: /* 2222 */
  1283. break;
  1284. /* single triangle cases */
  1285. case 169: /* 2221 */
  1286. shapeCoordinates.triangle_bl(cell, x0, x1, x2, x3, opt);
  1287. break;
  1288. case 166: /* 2212 */
  1289. shapeCoordinates.triangle_br(cell, x0, x1, x2, x3, opt);
  1290. break;
  1291. case 154: /* 2122 */
  1292. shapeCoordinates.triangle_tr(cell, x0, x1, x2, x3, opt);
  1293. break;
  1294. case 106: /* 1222 */
  1295. shapeCoordinates.triangle_tl(cell, x0, x1, x2, x3, opt);
  1296. break;
  1297. case 1: /* 0001 */
  1298. shapeCoordinates.triangle_bl(cell, x0, x1, x2, x3, opt);
  1299. break;
  1300. case 4: /* 0010 */
  1301. shapeCoordinates.triangle_br(cell, x0, x1, x2, x3, opt);
  1302. break;
  1303. case 16: /* 0100 */
  1304. shapeCoordinates.triangle_tr(cell, x0, x1, x2, x3, opt);
  1305. break;
  1306. case 64: /* 1000 */
  1307. shapeCoordinates.triangle_tl(cell, x0, x1, x2, x3, opt);
  1308. break;
  1309. /* single trapezoid cases */
  1310. case 168: /* 2220 */
  1311. shapeCoordinates.tetragon_bl(cell, x0, x1, x2, x3, opt);
  1312. break;
  1313. case 162: /* 2202 */
  1314. shapeCoordinates.tetragon_br(cell, x0, x1, x2, x3, opt);
  1315. break;
  1316. case 138: /* 2022 */
  1317. shapeCoordinates.tetragon_tr(cell, x0, x1, x2, x3, opt);
  1318. break;
  1319. case 42: /* 0222 */
  1320. shapeCoordinates.tetragon_tl(cell, x0, x1, x2, x3, opt);
  1321. break;
  1322. case 2: /* 0002 */
  1323. shapeCoordinates.tetragon_bl(cell, x0, x1, x2, x3, opt);
  1324. break;
  1325. case 8: /* 0020 */
  1326. shapeCoordinates.tetragon_br(cell, x0, x1, x2, x3, opt);
  1327. break;
  1328. case 32: /* 0200 */
  1329. shapeCoordinates.tetragon_tr(cell, x0, x1, x2, x3, opt);
  1330. break;
  1331. case 128: /* 2000 */
  1332. shapeCoordinates.tetragon_tl(cell, x0, x1, x2, x3, opt);
  1333. break;
  1334. /* single rectangle cases */
  1335. case 5: /* 0011 */
  1336. shapeCoordinates.tetragon_b(cell, x0, x1, x2, x3, opt);
  1337. break;
  1338. case 20: /* 0110 */
  1339. shapeCoordinates.tetragon_r(cell, x0, x1, x2, x3, opt);
  1340. break;
  1341. case 80: /* 1100 */
  1342. shapeCoordinates.tetragon_t(cell, x0, x1, x2, x3, opt);
  1343. break;
  1344. case 65: /* 1001 */
  1345. shapeCoordinates.tetragon_l(cell, x0, x1, x2, x3, opt);
  1346. break;
  1347. case 165: /* 2211 */
  1348. shapeCoordinates.tetragon_b(cell, x0, x1, x2, x3, opt);
  1349. break;
  1350. case 150: /* 2112 */
  1351. shapeCoordinates.tetragon_r(cell, x0, x1, x2, x3, opt);
  1352. break;
  1353. case 90: /* 1122 */
  1354. shapeCoordinates.tetragon_t(cell, x0, x1, x2, x3, opt);
  1355. break;
  1356. case 105: /* 1221 */
  1357. shapeCoordinates.tetragon_l(cell, x0, x1, x2, x3, opt);
  1358. break;
  1359. case 160: /* 2200 */
  1360. shapeCoordinates.tetragon_lr(cell, x0, x1, x2, x3, opt);
  1361. break;
  1362. case 130: /* 2002 */
  1363. shapeCoordinates.tetragon_tb(cell, x0, x1, x2, x3, opt);
  1364. break;
  1365. case 10: /* 0022 */
  1366. shapeCoordinates.tetragon_lr(cell, x0, x1, x2, x3, opt);
  1367. break;
  1368. case 40: /* 0220 */
  1369. shapeCoordinates.tetragon_tb(cell, x0, x1, x2, x3, opt);
  1370. break;
  1371. /* single pentagon cases */
  1372. case 101: /* 1211 */
  1373. shapeCoordinates.pentagon_tr(cell, x0, x1, x2, x3, opt);
  1374. break;
  1375. case 149: /* 2111 */
  1376. shapeCoordinates.pentagon_tl(cell, x0, x1, x2, x3, opt);
  1377. break;
  1378. case 86: /* 1112 */
  1379. shapeCoordinates.pentagon_bl(cell, x0, x1, x2, x3, opt);
  1380. break;
  1381. case 89: /* 1121 */
  1382. shapeCoordinates.pentagon_br(cell, x0, x1, x2, x3, opt);
  1383. break;
  1384. case 69: /* 1011 */
  1385. shapeCoordinates.pentagon_tr(cell, x0, x1, x2, x3, opt);
  1386. break;
  1387. case 21: /* 0111 */
  1388. shapeCoordinates.pentagon_tl(cell, x0, x1, x2, x3, opt);
  1389. break;
  1390. case 84: /* 1110 */
  1391. shapeCoordinates.pentagon_bl(cell, x0, x1, x2, x3, opt);
  1392. break;
  1393. case 81: /* 1101 */
  1394. shapeCoordinates.pentagon_br(cell, x0, x1, x2, x3, opt);
  1395. break;
  1396. case 96: /* 1200 */
  1397. shapeCoordinates.pentagon_tr_rl(cell, x0, x1, x2, x3, opt);
  1398. break;
  1399. case 24: /* 0120 */
  1400. shapeCoordinates.pentagon_rb_bt(cell, x0, x1, x2, x3, opt);
  1401. break;
  1402. case 6: /* 0012 */
  1403. shapeCoordinates.pentagon_bl_lr(cell, x0, x1, x2, x3, opt);
  1404. break;
  1405. case 129: /* 2001 */
  1406. shapeCoordinates.pentagon_lt_tb(cell, x0, x1, x2, x3, opt);
  1407. break;
  1408. case 74: /* 1022 */
  1409. shapeCoordinates.pentagon_tr_rl(cell, x0, x1, x2, x3, opt);
  1410. break;
  1411. case 146: /* 2102 */
  1412. shapeCoordinates.pentagon_rb_bt(cell, x0, x1, x2, x3, opt);
  1413. break;
  1414. case 164: /* 2210 */
  1415. shapeCoordinates.pentagon_bl_lr(cell, x0, x1, x2, x3, opt);
  1416. break;
  1417. case 41: /* 0221 */
  1418. shapeCoordinates.pentagon_lt_tb(cell, x0, x1, x2, x3, opt);
  1419. break;
  1420. case 66: /* 1002 */
  1421. shapeCoordinates.pentagon_bl_tb(cell, x0, x1, x2, x3, opt);
  1422. break;
  1423. case 144: /* 2100 */
  1424. shapeCoordinates.pentagon_lt_rl(cell, x0, x1, x2, x3, opt);
  1425. break;
  1426. case 36: /* 0210 */
  1427. shapeCoordinates.pentagon_tr_bt(cell, x0, x1, x2, x3, opt);
  1428. break;
  1429. case 9: /* 0021 */
  1430. shapeCoordinates.pentagon_rb_lr(cell, x0, x1, x2, x3, opt);
  1431. break;
  1432. case 104: /* 1220 */
  1433. shapeCoordinates.pentagon_bl_tb(cell, x0, x1, x2, x3, opt);
  1434. break;
  1435. case 26: /* 0122 */
  1436. shapeCoordinates.pentagon_lt_rl(cell, x0, x1, x2, x3, opt);
  1437. break;
  1438. case 134: /* 2012 */
  1439. shapeCoordinates.pentagon_tr_bt(cell, x0, x1, x2, x3, opt);
  1440. break;
  1441. case 161: /* 2201 */
  1442. shapeCoordinates.pentagon_rb_lr(cell, x0, x1, x2, x3, opt);
  1443. break;
  1444. /* single hexagon cases */
  1445. case 37: /* 0211 */
  1446. shapeCoordinates.hexagon_lt_tr(cell, x0, x1, x2, x3, opt);
  1447. break;
  1448. case 148: /* 2110 */
  1449. shapeCoordinates.hexagon_bl_lt(cell, x0, x1, x2, x3, opt);
  1450. break;
  1451. case 82: /* 1102 */
  1452. shapeCoordinates.hexagon_bl_rb(cell, x0, x1, x2, x3, opt);
  1453. break;
  1454. case 73: /* 1021 */
  1455. shapeCoordinates.hexagon_tr_rb(cell, x0, x1, x2, x3, opt);
  1456. break;
  1457. case 133: /* 2011 */
  1458. shapeCoordinates.hexagon_lt_tr(cell, x0, x1, x2, x3, opt);
  1459. break;
  1460. case 22: /* 0112 */
  1461. shapeCoordinates.hexagon_bl_lt(cell, x0, x1, x2, x3, opt);
  1462. break;
  1463. case 88: /* 1120 */
  1464. shapeCoordinates.hexagon_bl_rb(cell, x0, x1, x2, x3, opt);
  1465. break;
  1466. case 97: /* 1201 */
  1467. shapeCoordinates.hexagon_tr_rb(cell, x0, x1, x2, x3, opt);
  1468. break;
  1469. case 145: /* 2101 */
  1470. shapeCoordinates.hexagon_lt_rb(cell, x0, x1, x2, x3, opt);
  1471. break;
  1472. case 25: /* 0121 */
  1473. shapeCoordinates.hexagon_lt_rb(cell, x0, x1, x2, x3, opt);
  1474. break;
  1475. case 70: /* 1012 */
  1476. shapeCoordinates.hexagon_bl_tr(cell, x0, x1, x2, x3, opt);
  1477. break;
  1478. case 100: /* 1210 */
  1479. shapeCoordinates.hexagon_bl_tr(cell, x0, x1, x2, x3, opt);
  1480. break;
  1481. /* 6-sided saddles */
  1482. case 17: /* 0101 */
  1483. center_avg = computeCenterAverage(x0, x1, x2, x3, minV, maxV);
  1484. /* should never be center_avg === 2 */
  1485. if (center_avg === 0) {
  1486. shapeCoordinates.triangle_bl(cell, x0, x1, x2, x3, opt);
  1487. shapeCoordinates.triangle_tr(cell, x0, x1, x2, x3, opt);
  1488. } else {
  1489. shapeCoordinates.hexagon_lt_rb(cell, x0, x1, x2, x3, opt);
  1490. }
  1491. break;
  1492. case 68: /* 1010 */
  1493. center_avg = computeCenterAverage(x0, x1, x2, x3, minV, maxV);
  1494. /* should never be center_avg === 2 */
  1495. if (center_avg === 0) {
  1496. shapeCoordinates.triangle_tl(cell, x0, x1, x2, x3, opt);
  1497. shapeCoordinates.triangle_br(cell, x0, x1, x2, x3, opt);
  1498. } else {
  1499. shapeCoordinates.hexagon_bl_tr(cell, x0, x1, x2, x3, opt);
  1500. }
  1501. break;
  1502. case 153: /* 2121 */
  1503. center_avg = computeCenterAverage(x0, x1, x2, x3, minV, maxV);
  1504. /* should never be center_avg === 0 */
  1505. if (center_avg === 2) {
  1506. shapeCoordinates.triangle_bl(cell, x0, x1, x2, x3, opt);
  1507. shapeCoordinates.triangle_tr(cell, x0, x1, x2, x3, opt);
  1508. } else {
  1509. shapeCoordinates.hexagon_lt_rb(cell, x0, x1, x2, x3, opt);
  1510. }
  1511. break;
  1512. case 102: /* 1212 */
  1513. center_avg = computeCenterAverage(x0, x1, x2, x3, minV, maxV);
  1514. /* should never be center_avg === 0 */
  1515. if (center_avg === 2) {
  1516. shapeCoordinates.triangle_tl(cell, x0, x1, x2, x3, opt);
  1517. shapeCoordinates.triangle_br(cell, x0, x1, x2, x3, opt);
  1518. } else {
  1519. shapeCoordinates.hexagon_bl_tr(cell, x0, x1, x2, x3, opt);
  1520. }
  1521. break;
  1522. /* 7-sided saddles */
  1523. case 152: /* 2120 */
  1524. center_avg = computeCenterAverage(x0, x1, x2, x3, minV, maxV);
  1525. /* should never be center_avg === 0 */
  1526. if (center_avg === 2) {
  1527. shapeCoordinates.triangle_tr(cell, x0, x1, x2, x3, opt);
  1528. shapeCoordinates.tetragon_bl(cell, x0, x1, x2, x3, opt);
  1529. } else {
  1530. shapeCoordinates.heptagon_tr(cell, x0, x1, x2, x3, opt);
  1531. }
  1532. break;
  1533. case 137: /* 2021 */
  1534. center_avg = computeCenterAverage(x0, x1, x2, x3, minV, maxV);
  1535. /* should never be center_avg === 0 */
  1536. if (center_avg === 2) {
  1537. shapeCoordinates.triangle_bl(cell, x0, x1, x2, x3, opt);
  1538. shapeCoordinates.tetragon_tr(cell, x0, x1, x2, x3, opt);
  1539. } else {
  1540. shapeCoordinates.heptagon_bl(cell, x0, x1, x2, x3, opt);
  1541. }
  1542. break;
  1543. case 98: /* 1202 */
  1544. center_avg = computeCenterAverage(x0, x1, x2, x3, minV, maxV);
  1545. /* should never be center_avg === 0 */
  1546. if (center_avg === 2) {
  1547. shapeCoordinates.triangle_tl(cell, x0, x1, x2, x3, opt);
  1548. shapeCoordinates.tetragon_br(cell, x0, x1, x2, x3, opt);
  1549. } else {
  1550. shapeCoordinates.heptagon_tl(cell, x0, x1, x2, x3, opt);
  1551. }
  1552. break;
  1553. case 38: /* 0212 */
  1554. center_avg = computeCenterAverage(x0, x1, x2, x3, minV, maxV);
  1555. /* should never be center_avg === 0 */
  1556. if (center_avg === 2) {
  1557. shapeCoordinates.triangle_br(cell, x0, x1, x2, x3, opt);
  1558. shapeCoordinates.tetragon_tl(cell, x0, x1, x2, x3, opt);
  1559. } else {
  1560. shapeCoordinates.heptagon_br(cell, x0, x1, x2, x3, opt);
  1561. }
  1562. break;
  1563. case 18: /* 0102 */
  1564. center_avg = computeCenterAverage(x0, x1, x2, x3, minV, maxV);
  1565. /* should never be center_avg === 2 */
  1566. if (center_avg === 0) {
  1567. shapeCoordinates.triangle_tr(cell, x0, x1, x2, x3, opt);
  1568. shapeCoordinates.tetragon_bl(cell, x0, x1, x2, x3, opt);
  1569. } else {
  1570. shapeCoordinates.heptagon_tr(cell, x0, x1, x2, x3, opt);
  1571. }
  1572. break;
  1573. case 33: /* 0201 */
  1574. center_avg = computeCenterAverage(x0, x1, x2, x3, minV, maxV);
  1575. /* should never be center_avg === 2 */
  1576. if (center_avg === 0) {
  1577. shapeCoordinates.triangle_bl(cell, x0, x1, x2, x3, opt);
  1578. shapeCoordinates.tetragon_tr(cell, x0, x1, x2, x3, opt);
  1579. } else {
  1580. shapeCoordinates.heptagon_bl(cell, x0, x1, x2, x3, opt);
  1581. }
  1582. break;
  1583. case 72: /* 1020 */
  1584. center_avg = computeCenterAverage(x0, x1, x2, x3, minV, maxV);
  1585. /* should never be center_avg === 2 */
  1586. if (center_avg === 0) {
  1587. shapeCoordinates.triangle_tl(cell, x0, x1, x2, x3, opt);
  1588. shapeCoordinates.tetragon_br(cell, x0, x1, x2, x3, opt);
  1589. } else {
  1590. shapeCoordinates.heptagon_tl(cell, x0, x1, x2, x3, opt);
  1591. }
  1592. break;
  1593. case 132: /* 2010 */
  1594. center_avg = computeCenterAverage(x0, x1, x2, x3, minV, maxV);
  1595. /* should never be center_avg === 2 */
  1596. if (center_avg === 0) {
  1597. shapeCoordinates.triangle_br(cell, x0, x1, x2, x3, opt);
  1598. shapeCoordinates.tetragon_tl(cell, x0, x1, x2, x3, opt);
  1599. } else {
  1600. shapeCoordinates.heptagon_br(cell, x0, x1, x2, x3, opt);
  1601. }
  1602. break;
  1603. /* 8-sided saddles */
  1604. case 136: /* 2020 */
  1605. center_avg = computeCenterAverage(x0, x1, x2, x3, minV, maxV);
  1606. if (center_avg === 0) {
  1607. shapeCoordinates.tetragon_tl(cell, x0, x1, x2, x3, opt);
  1608. shapeCoordinates.tetragon_br(cell, x0, x1, x2, x3, opt);
  1609. } else if (center_avg === 1) {
  1610. shapeCoordinates.octagon(cell, x0, x1, x2, x3, opt);
  1611. } else {
  1612. shapeCoordinates.tetragon_bl(cell, x0, x1, x2, x3, opt);
  1613. shapeCoordinates.tetragon_tr(cell, x0, x1, x2, x3, opt);
  1614. }
  1615. break;
  1616. case 34: /* 0202 */
  1617. center_avg = computeCenterAverage(x0, x1, x2, x3, minV, maxV);
  1618. if (center_avg === 0) {
  1619. shapeCoordinates.tetragon_bl(cell, x0, x1, x2, x3, opt);
  1620. shapeCoordinates.tetragon_tr(cell, x0, x1, x2, x3, opt);
  1621. } else if (center_avg === 1) {
  1622. shapeCoordinates.octagon(cell, x0, x1, x2, x3, opt);
  1623. } else {
  1624. shapeCoordinates.tetragon_tl(cell, x0, x1, x2, x3, opt);
  1625. shapeCoordinates.tetragon_br(cell, x0, x1, x2, x3, opt);
  1626. }
  1627. break;
  1628. }
  1629. return cell;
  1630. }
  1631. export {isoBands};