| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410 |
- /*!
- * MarchingSquaresJS
- * version 1.3.3
- * https://github.com/RaumZeit/MarchingSquares.js
- *
- * @license GNU Affero General Public License.
- * Copyright (c) 2015-2019 Ronny Lorenz <ronny@tbi.univie.ac.at>
- */
- /*
- * Compute the distance of a value 'v' from 'a' through linear interpolation
- * between the values of 'a' and 'b'
- *
- * Note, that we assume that 'a' and 'b' have unit distance (i.e. 1)
- */
- function linear(a, b, v) {
- if (a < b)
- return (v - a) / (b - a);
- return (a - v) / (a - b);
- }
- /*
- * Compute the distance of a pair of values ('v0', 'v1') from 'a' through linear interpolation
- * between the values of 'a' and 'b'
- *
- * This function assumes that exactly one value, 'v0' or 'v1', is actually located
- * between 'a' and 'b', and choses the right one automagically
- *
- * Note, that we assume that 'a' and 'b' have unit distance (i.e. 1)
- */
- function linear_ab(a, b, v0, v1) {
- var tmp;
- if (v0 > v1) {
- tmp = v0;
- v0 = v1;
- v1 = tmp;
- }
- if (a < b) {
- if (a < v0)
- return (v0 - a) / (b - a);
- else
- return (v1 - a) / (b - a);
- } else if (a > v1) {
- return (a - v1) / (a - b);
- }
- return (a - v0) / (a - b);
- }
- /*
- * Compute the distance of a pair of values ('v0', 'v1') from 'a' through linear interpolation
- * between the values of 'a' and 'b'
- *
- * This function automagically choses the value 'vN' that is closer to 'a'
- *
- * Note, that we assume that 'a' and 'b' have unit distance (i.e. 1)
- */
- function linear_a(a, b, minV, maxV) {
- if (a < b)
- return (minV - a) / (b - a);
- return (a - maxV) / (a - b);
- }
- /*
- * Compute the distance of a pair of values ('v0', 'v1') from 'a' through linear interpolation
- * between the values of 'a' and 'b'
- *
- * This function automagically choses the value 'vN' that is closer to 'b'
- *
- * Note, that we assume that 'a' and 'b' have unit distance (i.e. 1)
- */
- function linear_b(a, b, minV, maxV) {
- if (a < b)
- return (maxV - a) / (b - a);
- return (a - minV) / (a - b);
- }
- function Options() {
- /* Settings common to all implemented algorithms */
- this.successCallback = null;
- this.verbose = false;
- this.polygons = false;
- this.polygons_full = false;
- this.linearRing = true;
- this.noQuadTree = false;
- this.noFrame = false;
- }
- /* Compose settings specific to IsoBands algorithm */
- function isoBandOptions(userSettings) {
- var i,
- key,
- val,
- bandOptions,
- optionKeys;
- bandOptions = new Options();
- userSettings = userSettings ? userSettings : {};
- optionKeys = Object.keys(bandOptions);
- for(i = 0; i < optionKeys.length; i++) {
- key = optionKeys[i];
- val = userSettings[key];
- if ((typeof val !== 'undefined') && (val !== null))
- bandOptions[key] = val;
- }
- /* restore compatibility */
- bandOptions.polygons_full = !bandOptions.polygons;
- /* add interpolation functions (not yet user customizable) */
- bandOptions.interpolate = linear_ab;
- bandOptions.interpolate_a = linear_a;
- bandOptions.interpolate_b = linear_b;
- return bandOptions;
- }
- /* Compose settings specific to IsoLines algorithm */
- function isoLineOptions(userSettings) {
- var i,
- key,
- val,
- lineOptions,
- optionKeys;
- lineOptions = new Options();
- userSettings = userSettings ? userSettings : {};
- optionKeys = Object.keys(lineOptions);
- for(i = 0; i < optionKeys.length; i++) {
- key = optionKeys[i];
- val = userSettings[key];
- if ((typeof val !== 'undefined') && (val !== null))
- lineOptions[key] = val;
- }
- /* restore compatibility */
- lineOptions.polygons_full = !lineOptions.polygons;
- /* add interpolation functions (not yet user customizable) */
- lineOptions.interpolate = linear;
- return lineOptions;
- }
- function cell2Polygons(cell, x, y, settings) {
- var polygons = [];
- cell.polygons.forEach(function(p) {
- p.forEach(function(pp) {
- pp[0] += x;
- pp[1] += y;
- });
- if (settings.linearRing)
- p.push(p[0]);
- polygons.push(p);
- });
- return polygons;
- }
- function entry_coordinate(x, y, mode, path) {
- if (mode === 0) { /* down */
- x += 1;
- y += path[0][1];
- } else if (mode === 1) { /* left */
- x += path[0][0];
- } else if (mode === 2) { /* up */
- y += path[0][1];
- } else if (mode === 3) { /* right */
- x += path[0][0];
- y += 1;
- }
- return [ x, y ];
- }
- function skip_coordinate(x, y, mode) {
- if (mode === 0) { /* down */
- x++;
- } else if (mode === 1) ; else if (mode === 2) { /* up */
- y++;
- } else if (mode === 3) { /* right */
- x++;
- y++;
- }
- return [ x, y ];
- }
- function requireFrame(data, lowerBound, upperBound) {
- var frameRequired,
- cols,
- rows,
- i,
- j;
- frameRequired = true;
- cols = data[0].length;
- rows = data.length;
- for (j = 0; j < rows; j++) {
- if ((data[j][0] < lowerBound) ||
- (data[j][0] > upperBound) ||
- (data[j][cols - 1] < lowerBound) ||
- (data[j][cols - 1] > upperBound)) {
- frameRequired = false;
- break;
- }
- }
- if ((frameRequired) &&
- ((data[rows - 1][0] < lowerBound) ||
- (data[rows - 1][0] > upperBound) ||
- (data[rows - 1][cols - 1] < lowerBound) ||
- (data[rows - 1][cols - 1] > upperBound))) {
- frameRequired = false;
- }
- if (frameRequired)
- for (i = 0; i < cols - 1; i++) {
- if ((data[0][i] < lowerBound) ||
- (data[0][i] > upperBound) ||
- (data[rows - 1][i] < lowerBound) ||
- (data[rows - 1][i] > upperBound)) {
- frameRequired = false;
- break;
- }
- }
- return frameRequired;
- }
- function requireLineFrame(data, threshold) {
- var frameRequired,
- cols,
- rows,
- i,
- j;
- frameRequired = true;
- cols = data[0].length;
- rows = data.length;
- for (j = 0; j < rows; j++) {
- if ((data[j][0] >= threshold) ||
- (data[j][cols - 1] >= threshold)) {
- frameRequired = false;
- break;
- }
- }
- if ((frameRequired) &&
- ((data[rows - 1][0] >= threshold) ||
- (data[rows - 1][cols - 1] >= threshold))) {
- frameRequired = false;
- }
- if (frameRequired)
- for (i = 0; i < cols - 1; i++) {
- if ((data[0][i] >= threshold) ||
- (data[rows - 1][i] > threshold)) {
- frameRequired = false;
- break;
- }
- }
- return frameRequired;
- }
- function traceBandPaths(data, cellGrid, settings) {
- var nextedge,
- path,
- e,
- ee,
- s,
- ve,
- enter,
- x,
- y,
- finalized,
- origin,
- cc,
- dir,
- count,
- point,
- found_entry;
- var polygons = [];
- var rows = data.length - 1;
- var cols = data[0].length - 1;
- /*
- * directions for out-of-grid moves are:
- * 0 ... "down",
- * 1 ... "left",
- * 2 ... "up",
- * 3 ... "right"
- */
- var valid_entries = [ ['rt', 'rb'], /* down */
- ['br', 'bl'], /* left */
- ['lb', 'lt'], /* up */
- ['tl', 'tr'] /* right */
- ];
- var add_x = [ 0, -1, 0, 1 ];
- var add_y = [ -1, 0, 1, 0 ];
- var available_starts = [ 'bl', 'lb', 'lt', 'tl', 'tr', 'rt', 'rb', 'br' ];
- var entry_dir = {
- bl: 1, br: 1,
- lb: 2, lt: 2,
- tl: 3, tr: 3,
- rt: 0, rb: 0
- };
- if (requireFrame(data, settings.minV, settings.maxV)) {
- if (settings.linearRing)
- polygons.push([ [0, 0], [0, rows], [cols, rows], [cols, 0], [0, 0] ]);
- else
- polygons.push([ [0, 0], [0, rows], [cols, rows], [cols, 0] ]);
- }
- /* finally, start tracing back first polygon(s) */
- cellGrid.forEach(function(a, i) {
- a.forEach(function(cell, j) {
- nextedge = null;
- /* trace paths for all available edges that go through this cell */
- for (e = 0; e < 8; e++) {
- nextedge = available_starts[e];
- if (typeof cell.edges[nextedge] !== 'object')
- continue;
- /* start a new, full path */
- path = [];
- ee = cell.edges[nextedge];
- enter = nextedge;
- x = i;
- y = j;
- finalized = false;
- origin = [ i + ee.path[0][0], j + ee.path[0][1] ];
- /* add start coordinate */
- path.push(origin);
- /* start traceback */
- while (!finalized) {
- cc = cellGrid[x][y];
- if (typeof cc.edges[enter] !== 'object')
- break;
- ee = cc.edges[enter];
- /* remove edge from cell */
- delete cc.edges[enter];
- /* add last point of edge to path arra, since we extend a polygon */
- point = ee.path[1];
- point[0] += x;
- point[1] += y;
- path.push(point);
- enter = ee.move.enter;
- x = x + ee.move.x;
- y = y + ee.move.y;
- /* handle out-of-grid moves */
- if ((typeof cellGrid[x] === 'undefined') ||
- (typeof cellGrid[x][y] === 'undefined')) {
- dir = 0;
- count = 0;
- if (x === cols) {
- x--;
- dir = 0; /* move downwards */
- } else if (x < 0) {
- x++;
- dir = 2; /* move upwards */
- } else if (y === rows) {
- y--;
- dir = 3; /* move right */
- } else if (y < 0) {
- y++;
- dir = 1; /* move left */
- } else {
- throw new Error('Left the grid somewhere in the interior!');
- }
- if ((x === i) && (y === j) && (dir === entry_dir[nextedge])) {
- finalized = true;
- enter = nextedge;
- break;
- }
- while (1) {
- found_entry = false;
- if (count > 4)
- throw new Error('Direction change counter overflow! This should never happen!');
- if (!((typeof cellGrid[x] === 'undefined') ||
- (typeof cellGrid[x][y] === 'undefined'))) {
- cc = cellGrid[x][y];
- /* check for re-entry */
- for (s = 0; s < valid_entries[dir].length; s++) {
- ve = valid_entries[dir][s];
- if (typeof cc.edges[ve] === 'object') {
- /* found re-entry */
- ee = cc.edges[ve];
- path.push(entry_coordinate(x, y, dir, ee.path));
- enter = ve;
- found_entry = true;
- break;
- }
- }
- }
- if (found_entry) {
- break;
- } else {
- path.push(skip_coordinate(x, y, dir));
- x += add_x[dir];
- y += add_y[dir];
- /* change direction if we'e moved out of grid again */
- if ((typeof cellGrid[x] === 'undefined') ||
- (typeof cellGrid[x][y] === 'undefined')) {
- if (((dir === 0) && (y < 0)) ||
- ((dir === 1) && (x < 0)) ||
- ((dir === 2) && (y === rows)) ||
- ((dir === 3) && (x === cols))) {
- x -= add_x[dir];
- y -= add_y[dir];
- dir = (dir + 1) % 4;
- count++;
- }
- }
- if ((x === i) && (y === j) && (dir === entry_dir[nextedge])) {
- /* we are back where we started off, so finalize the polygon */
- finalized = true;
- enter = nextedge;
- break;
- }
- }
- }
- }
- }
- if ((settings.linearRing) &&
- ((path[path.length - 1][0] !== origin[0]) ||
- (path[path.length - 1][1] !== origin[1])))
- path.push(origin);
- polygons.push(path);
- } /* end forall entry sites */
- }); /* end foreach i */
- }); /* end foreach j */
- return polygons;
- }
- function traceLinePaths(data, cellGrid, settings) {
- var nextedge,
- e,
- ee,
- cc,
- path,
- enter,
- x,
- y,
- finalized,
- origin,
- point,
- dir,
- count,
- found_entry,
- ve;
- var polygons = [];
- var rows = data.length - 1;
- var cols = data[0].length - 1;
- /*
- * directions for out-of-grid moves are:
- * 0 ... "down",
- * 1 ... "left",
- * 2 ... "up",
- * 3 ... "right"
- */
- var valid_entries = [ 'right', /* down */
- 'bottom', /* left */
- 'left', /* up */
- 'top' /* right */
- ];
- var add_x = [ 0, -1, 0, 1 ];
- var add_y = [ -1, 0, 1, 0 ];
- var entry_dir = {
- bottom: 1,
- left: 2,
- top: 3,
- right: 0
- };
- /* first, detect whether we need any outer frame */
- if (!settings.noFrame)
- if (requireLineFrame(data, settings.threshold)) {
- if (settings.linearRing)
- polygons.push([ [0, 0], [0, rows], [cols, rows], [cols, 0], [0, 0] ]);
- else
- polygons.push([ [0, 0], [0, rows], [cols, rows], [cols, 0] ]);
- }
- /* finally, start tracing back first polygon(s) */
- cellGrid.forEach(function(a, i) {
- a.forEach(function(cell, j) {
- nextedge = null;
- /* trace paths for all available edges that go through this cell */
- for (e = 0; e < 4; e++) {
- nextedge = valid_entries[e];
- if (typeof cell.edges[nextedge] !== 'object')
- continue;
- /* start a new, full path */
- path = [];
- ee = cell.edges[nextedge];
- enter = nextedge;
- x = i;
- y = j;
- finalized = false;
- origin = [ i + ee.path[0][0], j + ee.path[0][1] ];
- /* add start coordinate */
- path.push(origin);
- /* start traceback */
- while (!finalized) {
- cc = cellGrid[x][y];
- if (typeof cc.edges[enter] !== 'object')
- break;
- ee = cc.edges[enter];
- /* remove edge from cell */
- delete cc.edges[enter];
- /* add last point of edge to path arra, since we extend a polygon */
- point = ee.path[1];
- point[0] += x;
- point[1] += y;
- path.push(point);
- enter = ee.move.enter;
- x = x + ee.move.x;
- y = y + ee.move.y;
- /* handle out-of-grid moves */
- if ((typeof cellGrid[x] === 'undefined') ||
- (typeof cellGrid[x][y] === 'undefined')) {
- if (!settings.linearRing)
- break;
- dir = 0;
- count = 0;
- if (x === cols) {
- x--;
- dir = 0; /* move downwards */
- } else if (x < 0) {
- x++;
- dir = 2; /* move upwards */
- } else if (y === rows) {
- y--;
- dir = 3; /* move right */
- } else if (y < 0) {
- y++;
- dir = 1; /* move left */
- }
- if ((x === i) && (y === j) && (dir === entry_dir[nextedge])) {
- finalized = true;
- enter = nextedge;
- break;
- }
- while (1) {
- found_entry = false;
- if (count > 4)
- throw new Error('Direction change counter overflow! This should never happen!');
- if (!((typeof cellGrid[x] === 'undefined') ||
- (typeof cellGrid[x][y] === 'undefined'))) {
- cc = cellGrid[x][y];
- /* check for re-entry */
- ve = valid_entries[dir];
- if (typeof cc.edges[ve] === 'object') {
- /* found re-entry */
- ee = cc.edges[ve];
- path.push(entry_coordinate(x, y, dir, ee.path));
- enter = ve;
- found_entry = true;
- break;
- }
- }
- if (found_entry) {
- break;
- } else {
- path.push(skip_coordinate(x, y, dir));
- x += add_x[dir];
- y += add_y[dir];
- /* change direction if we'e moved out of grid again */
- if ((typeof cellGrid[x] === 'undefined') ||
- (typeof cellGrid[x][y] === 'undefined')) {
- if (((dir === 0) && (y < 0)) ||
- ((dir === 1) && (x < 0)) ||
- ((dir === 2) && (y === rows)) ||
- ((dir === 3) && (x === cols))) {
- x -= add_x[dir];
- y -= add_y[dir];
- dir = (dir + 1) % 4;
- count++;
- }
- }
- if ((x === i) && (y === j) && (dir === entry_dir[nextedge])) {
- /* we are back where we started off, so finalize the polygon */
- finalized = true;
- enter = nextedge;
- break;
- }
- }
- }
- }
- }
- if ((settings.linearRing) &&
- ((path[path.length - 1][0] !== origin[0]) ||
- (path[path.length - 1][1] !== origin[1])))
- path.push(origin);
- polygons.push(path);
- } /* end forall entry sites */
- }); /* end foreach i */
- }); /* end foreach j */
- return polygons;
- }
- /* quadTree node constructor */
- function TreeNode(data, x, y, dx, dy) {
- var dx_tmp = dx,
- dy_tmp = dy,
- msb_x = 0,
- msb_y = 0;
- /* left-bottom corner of current quadrant */
- this.x = x;
- this.y = y;
- /* minimum value in subtree under this node */
- this.lowerBound = null;
- /* maximum value in subtree under this node */
- this.upperBound = null;
- /*
- * child nodes are layed out in the following way:
- *
- * (x, y + 1) ---- (x + 1, y + 1)
- * | | |
- * | D | C |
- * | | |
- * |----------------------------|
- * | | |
- * | A | B |
- * | | |
- * (x, y) ------------ (x + 1, y)
- */
- this.childA = null;
- this.childB = null;
- this.childC = null;
- this.childD = null;
- if ((dx === 1) && (dy === 1)) {
- /* do not further subdivision */
- this.lowerBound = Math.min(
- data[y][x],
- data[y][x + 1],
- data[y + 1][x + 1],
- data[y + 1][x]
- );
- this.upperBound = Math.max(
- data[y][x],
- data[y][x + 1],
- data[y + 1][x + 1],
- data[y + 1][x]
- );
- } else {
- /* get most significant bit from dx */
- if (dx > 1) {
- while (dx_tmp !== 0) {
- dx_tmp = dx_tmp >> 1;
- msb_x++;
- }
- if (dx === (1 << (msb_x - 1)))
- msb_x--;
- dx_tmp = 1 << (msb_x - 1);
- }
- /* get most significant bit from dx */
- if (dy > 1) {
- while (dy_tmp !== 0) {
- dy_tmp = dy_tmp >> 1;
- msb_y++;
- }
- if (dy === (1 << (msb_y - 1)))
- msb_y--;
- dy_tmp = 1 << (msb_y - 1);
- }
- this.childA = new TreeNode(data, x, y, dx_tmp, dy_tmp);
- this.lowerBound = this.childA.lowerBound;
- this.upperBound = this.childA.upperBound;
- if (dx - dx_tmp > 0) {
- this.childB = new TreeNode(data, x + dx_tmp, y, dx - dx_tmp, dy_tmp);
- this.lowerBound = Math.min(this.lowerBound, this.childB.lowerBound);
- this.upperBound = Math.max(this.upperBound, this.childB.upperBound);
- if (dy - dy_tmp > 0) {
- this.childC = new TreeNode(data, x + dx_tmp, y + dy_tmp, dx - dx_tmp, dy - dy_tmp);
- this.lowerBound = Math.min(this.lowerBound, this.childC.lowerBound);
- this.upperBound = Math.max(this.upperBound, this.childC.upperBound);
- }
- }
- if (dy - dy_tmp > 0) {
- this.childD = new TreeNode(data, x, y + dy_tmp, dx_tmp, dy - dy_tmp);
- this.lowerBound = Math.min(this.lowerBound, this.childD.lowerBound);
- this.upperBound = Math.max(this.upperBound, this.childD.upperBound);
- }
- }
- }
- /**
- * Retrieve a list of cells within a particular range of values by
- * recursivly traversing the quad tree to it's leaves.
- *
- * @param subsumed If 'true' include all cells that are completely
- * subsumed within the specified range. Otherwise,
- * return only cells where at least one corner is
- * outside the specified range.
- *
- * @return An array of objects 'o' where each object has exactly two
- * properties: 'o.x' and 'o.y' denoting the left-bottom corner
- * of the corresponding cell.
- */
- TreeNode.prototype.cellsInBand = function(lowerBound, upperBound, subsumed) {
- var cells = [];
- subsumed = (typeof subsumed === 'undefined') ? true : subsumed;
- if ((this.lowerBound > upperBound) || (this.upperBound < lowerBound))
- return cells;
- if (!(this.childA || this.childB || this.childC || this.childD)) {
- if ((subsumed) ||
- (this.lowerBound <= lowerBound) ||
- (this.upperBound >= upperBound)) {
- cells.push({
- x: this.x,
- y: this.y
- });
- }
- } else {
- if (this.childA)
- cells = cells.concat(this.childA.cellsInBand(lowerBound, upperBound, subsumed));
- if (this.childB)
- cells = cells.concat(this.childB.cellsInBand(lowerBound, upperBound, subsumed));
- if (this.childD)
- cells = cells.concat(this.childD.cellsInBand(lowerBound, upperBound, subsumed));
- if (this.childC)
- cells = cells.concat(this.childC.cellsInBand(lowerBound, upperBound, subsumed));
- }
- return cells;
- };
- TreeNode.prototype.cellsBelowThreshold = function(threshold, subsumed) {
- var cells = [];
- subsumed = (typeof subsumed === 'undefined') ? true : subsumed;
- if (this.lowerBound > threshold)
- return cells;
- if (!(this.childA || this.childB || this.childC || this.childD)) {
- if ((subsumed) ||
- (this.upperBound >= threshold)) {
- cells.push({
- x: this.x,
- y: this.y
- });
- }
- } else {
- if (this.childA)
- cells = cells.concat(this.childA.cellsBelowThreshold(threshold, subsumed));
- if (this.childB)
- cells = cells.concat(this.childB.cellsBelowThreshold(threshold, subsumed));
- if (this.childD)
- cells = cells.concat(this.childD.cellsBelowThreshold(threshold, subsumed));
- if (this.childC)
- cells = cells.concat(this.childC.cellsBelowThreshold(threshold, subsumed));
- }
- return cells;
- };
- /*
- * Given a scalar field `data` construct a QuadTree
- * to efficiently lookup those parts of the scalar
- * field where values are within a particular
- * range of [lowerbound, upperbound] limits.
- */
- function QuadTree(data) {
- var i, cols;
- /* do some input checking */
- if (!data)
- throw new Error('data is required');
- if (!Array.isArray(data) ||
- !Array.isArray(data[0]))
- throw new Error('data must be scalar field, i.e. array of arrays');
- if (data.length < 2)
- throw new Error('data must contain at least two rows');
- /* check if we've got a regular grid */
- cols = data[0].length;
- if (cols < 2)
- throw new Error('data must contain at least two columns');
- for (i = 1; i < data.length; i++) {
- if (!Array.isArray(data[i]))
- throw new Error('Row ' + i + ' is not an array');
- if (data[i].length != cols)
- throw new Error('unequal row lengths detected, please provide a regular grid');
- }
- /* create pre-processing object */
- this.data = data;
- /* root node, i.e. entry to the data */
- this.root = new TreeNode(data, 0, 0, data[0].length - 1, data.length - 1);
- }
- /* eslint no-console: ["error", { allow: ["log"] }] */
- /*
- * Compute the iso lines for a scalar 2D field given
- * a certain threshold by applying the Marching Squares
- * Algorithm. The function returns a list of path coordinates
- */
- function isoLines(input, threshold, options) {
- var settings,
- i,
- j,
- useQuadTree = false,
- multiLine = false,
- tree = null,
- root = null,
- data = null,
- cellGrid = null,
- linePolygons = null,
- ret = [];
- /* validation */
- if (!input) throw new Error('data is required');
- if (threshold === undefined || threshold === null) throw new Error('threshold is required');
- if ((!!options) && (typeof options !== 'object')) throw new Error('options must be an object');
- /* process options */
- settings = isoLineOptions(options);
- /* check for input data */
- if (input instanceof QuadTree) {
- tree = input;
- root = input.root;
- data = input.data;
- if (!settings.noQuadTree)
- useQuadTree = true;
- } else if (Array.isArray(input) && Array.isArray(input[0])) {
- data = input;
- } else {
- throw new Error('input is neither array of arrays nor object retrieved from \'QuadTree()\'');
- }
- /* check and prepare input threshold(s) */
- if (Array.isArray(threshold)) {
- multiLine = true;
- /* activate QuadTree optimization if not explicitly forbidden by user settings */
- if (!settings.noQuadTree)
- useQuadTree = true;
- /* check if all minV are numbers */
- for (i = 0; i < threshold.length; i++)
- if (isNaN(+threshold[i]))
- throw new Error('threshold[' + i + '] is not a number');
- } else {
- if (isNaN(+threshold))
- throw new Error('threshold must be a number or array of numbers');
- threshold = [ threshold ];
- }
- /* create QuadTree root node if not already present */
- if ((useQuadTree) && (!root)) {
- tree = new QuadTree(data);
- root = tree.root;
- data = tree.data;
- }
- if (settings.verbose) {
- if(settings.polygons)
- console.log('MarchingSquaresJS-isoLines: returning single lines (polygons) for each grid cell');
- else
- console.log('MarchingSquaresJS-isoLines: returning line paths (polygons) for entire data grid');
- if (multiLine)
- console.log('MarchingSquaresJS-isoLines: multiple lines requested, returning array of line paths instead of lines for a single threshold');
- }
- /* Done with all input validation, now let's start computing stuff */
- /* loop over all threhsold values */
- threshold.forEach(function(t, i) {
- linePolygons = [];
- /* store bounds for current computation in settings object */
- settings.threshold = t;
- if(settings.verbose)
- console.log('MarchingSquaresJS-isoLines: computing iso lines for threshold ' + t);
- if (settings.polygons) {
- /* compose list of polygons for each single cell */
- if (useQuadTree) {
- /* go through list of cells retrieved from QuadTree */
- root
- .cellsBelowThreshold(settings.threshold, true)
- .forEach(function(c) {
- linePolygons = linePolygons.concat(
- cell2Polygons(
- prepareCell(data,
- c.x,
- c.y,
- settings),
- c.x,
- c.y,
- settings
- ));
- });
- } else {
- /* go through entire array of input data */
- for (j = 0; j < data.length - 1; ++j) {
- for (i = 0; i < data[0].length - 1; ++i)
- linePolygons = linePolygons.concat(
- cell2Polygons(
- prepareCell(data,
- i,
- j,
- settings),
- i,
- j,
- settings
- ));
- }
- }
- } else {
- /* sparse grid of input data cells */
- cellGrid = [];
- for (i = 0; i < data[0].length - 1; ++i)
- cellGrid[i] = [];
- /* compose list of polygons for entire input grid */
- if (useQuadTree) {
- /* collect the cells */
- root
- .cellsBelowThreshold(settings.threshold, false)
- .forEach(function(c) {
- cellGrid[c.x][c.y] = prepareCell(data,
- c.x,
- c.y,
- settings);
- });
- } else {
- /* prepare cells */
- for (i = 0; i < data[0].length - 1; ++i) {
- for (j = 0; j < data.length - 1; ++j) {
- cellGrid[i][j] = prepareCell(data,
- i,
- j,
- settings);
- }
- }
- }
- linePolygons = traceLinePaths(data, cellGrid, settings);
- }
- /* finally, add polygons to output array */
- if (multiLine)
- ret.push(linePolygons);
- else
- ret = linePolygons;
- if(typeof settings.successCallback === 'function')
- settings.successCallback(ret, t);
- });
- return ret;
- }
- /*
- * Thats all for the public interface, below follows the actual
- * implementation
- */
- /*
- * ################################
- * Isocontour implementation below
- * ################################
- */
- function prepareCell(grid, x, y, settings) {
- var left,
- right,
- top,
- bottom,
- average,
- cell;
- var cval = 0;
- var x3 = grid[y + 1][x];
- var x2 = grid[y + 1][x + 1];
- var x1 = grid[y][x + 1];
- var x0 = grid[y][x];
- var threshold = settings.threshold;
- /*
- * Note that missing data within the grid will result
- * in horribly failing to trace full polygon paths
- */
- if(isNaN(x0) || isNaN(x1) || isNaN(x2) || isNaN(x3)) {
- return;
- }
- /*
- * Here we detect the type of the cell
- *
- * x3 ---- x2
- * | |
- * | |
- * x0 ---- x1
- *
- * with edge points
- *
- * x0 = (x,y),
- * x1 = (x + 1, y),
- * x2 = (x + 1, y + 1), and
- * x3 = (x, y + 1)
- *
- * and compute the polygon intersections with the edges
- * of the cell. Each edge value may be (i) smaller, or (ii)
- * greater or equal to the iso line threshold. We encode
- * this property using 1 bit of information, where
- *
- * 0 ... below,
- * 1 ... above or equal
- *
- * Then we store the cells value as vector
- *
- * cval = (x0, x1, x2, x3)
- *
- * where x0 is the least significant bit (0th),
- * x1 the 2nd bit, and so on. This essentially
- * enables us to work with a single integer number
- */
- cval |= ((x3 >= threshold) ? 8 : 0);
- cval |= ((x2 >= threshold) ? 4 : 0);
- cval |= ((x1 >= threshold) ? 2 : 0);
- cval |= ((x0 >= threshold) ? 1 : 0);
- /* make sure cval is a number */
- cval = +cval;
- /* compose the cell object */
- cell = {
- cval: cval,
- polygons: [],
- edges: {},
- x0: x0,
- x1: x1,
- x2: x2,
- x3: x3
- };
- /*
- * Compute interpolated intersections of the polygon(s)
- * with the cell borders and (i) add edges for polygon
- * trace-back, or (ii) a list of small closed polygons
- */
- switch (cval) {
- case 0:
- if (settings.polygons)
- cell.polygons.push([ [0, 0], [0, 1], [1, 1], [1, 0] ]);
- break;
- case 15:
- /* cell is outside (above) threshold, no polygons */
- break;
- case 14: /* 1110 */
- left = settings.interpolate(x0, x3, threshold);
- bottom = settings.interpolate(x0, x1, threshold);
- if (settings.polygons_full) {
- cell.edges.left = {
- path: [ [0, left], [bottom, 0] ],
- move: {
- x: 0,
- y: -1,
- enter: 'top'
- }
- };
- }
- if (settings.polygons)
- cell.polygons.push([ [0, 0], [0, left], [bottom, 0] ]);
- break;
- case 13: /* 1101 */
- bottom = settings.interpolate(x0, x1, threshold);
- right = settings.interpolate(x1, x2, threshold);
- if (settings.polygons_full) {
- cell.edges.bottom = {
- path: [ [bottom, 0], [1, right] ],
- move: {
- x: 1,
- y: 0,
- enter: 'left'
- }
- };
- }
- if (settings.polygons)
- cell.polygons.push([ [bottom, 0], [1, right], [1, 0] ]);
- break;
- case 11: /* 1011 */
- right = settings.interpolate(x1, x2, threshold);
- top = settings.interpolate(x3, x2, threshold);
- if (settings.polygons_full) {
- cell.edges.right = {
- path: [ [1, right], [top, 1] ],
- move: {
- x: 0,
- y: 1,
- enter: 'bottom'
- }
- };
- }
- if (settings.polygons)
- cell.polygons.push([ [1, right], [top, 1], [1, 1] ]);
- break;
- case 7: /* 0111 */
- left = settings.interpolate(x0, x3, threshold);
- top = settings.interpolate(x3, x2, threshold);
- if (settings.polygons_full) {
- cell.edges.top = {
- path: [ [top, 1], [0, left] ],
- move: {
- x: -1,
- y: 0,
- enter: 'right'
- }
- };
- }
- if (settings.polygons)
- cell.polygons.push([ [top, 1], [0, left], [0, 1] ]);
- break;
- case 1: /* 0001 */
- left = settings.interpolate(x0, x3, threshold);
- bottom = settings.interpolate(x0, x1, threshold);
- if (settings.polygons_full) {
- cell.edges.bottom = {
- path: [ [bottom, 0], [0, left] ],
- move: {
- x: -1,
- y: 0,
- enter: 'right'
- }
- };
- }
- if (settings.polygons)
- cell.polygons.push([ [bottom, 0], [0, left], [0, 1], [1, 1], [1, 0] ]);
- break;
- case 2: /* 0010 */
- bottom = settings.interpolate(x0, x1, threshold);
- right = settings.interpolate(x1, x2, threshold);
- if (settings.polygons_full) {
- cell.edges.right = {
- path: [ [1, right], [bottom, 0] ],
- move: {
- x: 0,
- y: -1,
- enter: 'top'
- }
- };
- }
- if (settings.polygons)
- cell.polygons.push([ [0, 0], [0, 1], [1, 1], [1, right], [bottom, 0] ]);
- break;
- case 4: /* 0100 */
- right = settings.interpolate(x1, x2, threshold);
- top = settings.interpolate(x3, x2, threshold);
- if (settings.polygons_full) {
- cell.edges.top = {
- path: [ [top, 1], [1, right] ],
- move: {
- x: 1,
- y: 0,
- enter: 'left'
- }
- };
- }
- if (settings.polygons)
- cell.polygons.push([ [0, 0], [0, 1], [top, 1], [1, right], [1, 0] ]);
- break;
- case 8: /* 1000 */
- left = settings.interpolate(x0, x3, threshold);
- top = settings.interpolate(x3, x2, threshold);
- if (settings.polygons_full) {
- cell.edges.left = {
- path: [ [0, left], [top, 1] ],
- move: {
- x: 0,
- y: 1,
- enter: 'bottom'
- }
- };
- }
- if (settings.polygons)
- cell.polygons.push([ [0, 0], [0, left], [top, 1], [1, 1], [1, 0] ]);
- break;
- case 12: /* 1100 */
- left = settings.interpolate(x0, x3, threshold);
- right = settings.interpolate(x1, x2, threshold);
- if (settings.polygons_full) {
- cell.edges.left = {
- path: [ [0, left], [1, right] ],
- move: {
- x: 1,
- y: 0,
- enter: 'left'
- }
- };
- }
- if (settings.polygons)
- cell.polygons.push([ [0, 0], [0, left], [1, right], [1, 0] ]);
- break;
- case 9: /* 1001 */
- bottom = settings.interpolate(x0, x1, threshold);
- top = settings.interpolate(x3, x2, threshold);
- if (settings.polygons_full) {
- cell.edges.bottom = {
- path: [ [bottom, 0], [top, 1] ],
- move: {
- x: 0,
- y: 1,
- enter: 'bottom'
- }
- };
- }
- if (settings.polygons)
- cell.polygons.push([ [bottom, 0], [top, 1], [1, 1], [1, 0] ]);
- break;
- case 3: /* 0011 */
- left = settings.interpolate(x0, x3, threshold);
- right = settings.interpolate(x1, x2, threshold);
- if (settings.polygons_full) {
- cell.edges.right = {
- path: [ [1, right], [0, left] ],
- move: {
- x: -1,
- y: 0,
- enter: 'right'
- }
- };
- }
- if (settings.polygons)
- cell.polygons.push([ [0, left], [0, 1], [1, 1], [1, right] ]);
- break;
- case 6: /* 0110 */
- bottom = settings.interpolate(x0, x1, threshold);
- top = settings.interpolate(x3, x2, threshold);
- if (settings.polygons_full) {
- cell.edges.top = {
- path: [ [top, 1], [bottom, 0] ],
- move: {
- x: 0,
- y: -1,
- enter: 'top'
- }
- };
- }
- if (settings.polygons)
- cell.polygons.push([ [0, 0], [0, 1], [top, 1], [bottom, 0] ]);
- break;
- case 10: /* 1010 */
- left = settings.interpolate(x0, x3, threshold);
- right = settings.interpolate(x1, x2, threshold);
- bottom = settings.interpolate(x0, x1, threshold);
- top = settings.interpolate(x3, x2, threshold);
- average = (x0 + x1 + x2 + x3) / 4;
- if (settings.polygons_full) {
- if (average < threshold) {
- cell.edges.left = {
- path: [ [0, left], [top, 1] ],
- move: {
- x: 0,
- y: 1,
- enter: 'bottom'
- }
- };
- cell.edges.right = {
- path: [ [1, right], [bottom, 0] ],
- move: {
- x: 0,
- y: -1,
- enter: 'top'
- }
- };
- } else {
- cell.edges.right = {
- path: [ [1, right], [top, 1] ],
- move: {
- x: 0,
- y: 1,
- enter: 'bottom'
- }
- };
- cell.edges.left = {
- path: [ [0, left], [bottom, 0] ],
- move: {
- x: 0,
- y: -1,
- enter: 'top'
- }
- };
- }
- }
- if (settings.polygons) {
- if (average < threshold) {
- cell.polygons.push([ [0, 0], [0, left], [top, 1], [1, 1], [1, right], [bottom, 0] ]);
- } else {
- cell.polygons.push([ [0, 0], [0, left], [bottom, 0] ]);
- cell.polygons.push([ [top, 1], [1, 1], [1, right] ]);
- }
- }
- break;
- case 5: /* 0101 */
- left = settings.interpolate(x0, x3, threshold);
- right = settings.interpolate(x1, x2, threshold);
- bottom = settings.interpolate(x0, x1, threshold);
- top = settings.interpolate(x3, x2, threshold);
- average = (x0 + x1 + x2 + x3) / 4;
- if (settings.polygons_full) {
- if (average < threshold) {
- cell.edges.bottom = {
- path: [ [bottom, 0], [0, left] ],
- move: {
- x: -1,
- y: 0,
- enter: 'right'
- }
- };
- cell.edges.top = {
- path: [ [top, 1], [1, right] ],
- move: {
- x: 1,
- y: 0,
- enter: 'left'
- }
- };
- } else {
- cell.edges.top = {
- path: [ [top, 1], [0, left] ],
- move: {
- x: -1,
- y: 0,
- enter: 'right'
- }
- };
- cell.edges.bottom = {
- path: [ [bottom, 0], [1, right] ],
- move: {
- x: 1,
- y: 0,
- enter: 'left'
- }
- };
- }
- }
- if (settings.polygons) {
- if (average < threshold) {
- cell.polygons.push([ [0, left], [0, 1], [top, 1], [1, right], [1, 0], [bottom, 0] ]);
- } else {
- cell.polygons.push([ [0, left], [0, 1], [top, 1] ]);
- cell.polygons.push([ [bottom, 0], [1, right], [1, 0] ]);
- }
- }
- break;
- }
- return cell;
- }
- /* eslint no-console: ["error", { allow: ["log"] }] */
- /*
- * lookup table to generate polygon paths or edges required to
- * trace the full polygon(s)
- */
- var shapeCoordinates = {
- square: function(cell, x0, x1, x2, x3, opt) {
- if (opt.polygons)
- cell.polygons.push([ [0,0], [0, 1], [1, 1], [1, 0] ]);
- },
- triangle_bl: function(cell, x0, x1, x2, x3, opt) {
- var bottomleft = opt.interpolate(x0, x1, opt.minV, opt.maxV);
- var leftbottom = opt.interpolate(x0, x3, opt.minV, opt.maxV);
- if (opt.polygons_full) {
- cell.edges.lb = {
- path: [ [0, leftbottom], [bottomleft, 0] ],
- move: {
- x: 0,
- y: -1,
- enter: 'tl'
- }
- };
- }
- if (opt.polygons)
- cell.polygons.push([ [0, leftbottom], [bottomleft, 0], [0, 0] ]);
- },
- triangle_br: function(cell, x0, x1, x2, x3, opt) {
- var bottomright = opt.interpolate(x0, x1, opt.minV, opt.maxV);
- var rightbottom = opt.interpolate(x1, x2, opt.minV, opt.maxV);
- if (opt.polygons_full) {
- cell.edges.br = {
- path: [ [bottomright, 0], [1, rightbottom] ],
- move: {
- x: 1,
- y: 0,
- enter: 'lb'
- }
- };
- }
- if (opt.polygons)
- cell.polygons.push([ [bottomright, 0], [1, rightbottom], [1, 0] ]);
- },
- triangle_tr: function(cell, x0, x1, x2, x3, opt) {
- var righttop = opt.interpolate(x1, x2, opt.minV, opt.maxV);
- var topright = opt.interpolate(x3, x2, opt.minV, opt.maxV);
- if (opt.polygons_full) {
- cell.edges.rt = {
- path: [ [1, righttop], [topright, 1] ],
- move: {
- x: 0,
- y: 1,
- enter: 'br'
- }
- };
- }
- if (opt.polygons)
- cell.polygons.push([ [1, righttop], [topright, 1], [1, 1] ]);
- },
- triangle_tl: function(cell, x0, x1, x2, x3, opt) {
- var topleft = opt.interpolate(x3, x2, opt.minV, opt.maxV);
- var lefttop = opt.interpolate(x0, x3, opt.minV, opt.maxV);
- if (opt.polygons_full) {
- cell.edges.tl = {
- path: [ [topleft, 1], [0, lefttop] ],
- move: {
- x: -1,
- y: 0,
- enter: 'rt'
- }
- };
- }
- if (opt.polygons)
- cell.polygons.push([ [0, lefttop], [0, 1], [topleft, 1] ]);
- },
- tetragon_t: function(cell, x0, x1, x2, x3, opt) {
- var righttop = opt.interpolate(x1, x2, opt.minV, opt.maxV);
- var lefttop = opt.interpolate(x0, x3, opt.minV, opt.maxV);
- if (opt.polygons_full) {
- cell.edges.rt = {
- path: [ [1, righttop], [0, lefttop] ],
- move: {
- x: -1,
- y: 0,
- enter: 'rt'
- }
- };
- }
- if (opt.polygons)
- cell.polygons.push([ [0, lefttop], [0, 1], [1, 1], [1, righttop] ]);
- },
- tetragon_r: function(cell, x0, x1, x2, x3, opt) {
- var bottomright = opt.interpolate(x0, x1, opt.minV, opt.maxV);
- var topright = opt.interpolate(x3, x2, opt.minV, opt.maxV);
- if (opt.polygons_full) {
- cell.edges.br = {
- path: [ [bottomright, 0], [topright, 1] ],
- move: {
- x: 0,
- y: 1,
- enter: 'br'
- }
- };
- }
- if (opt.polygons)
- cell.polygons.push([ [bottomright, 0], [topright, 1], [1, 1], [1, 0] ]);
- },
- tetragon_b: function(cell, x0, x1, x2, x3, opt) {
- var leftbottom = opt.interpolate(x0, x3, opt.minV, opt.maxV);
- var rightbottom = opt.interpolate(x1, x2, opt.minV, opt.maxV);
- if (opt.polygons_full) {
- cell.edges.lb = {
- path: [ [0, leftbottom], [1, rightbottom] ],
- move: {
- x: 1,
- y: 0,
- enter: 'lb'
- }
- };
- }
- if (opt.polygons)
- cell.polygons.push([ [0, 0], [0, leftbottom], [1, rightbottom], [1, 0] ]);
- },
- tetragon_l: function(cell, x0, x1, x2, x3, opt) {
- var topleft = opt.interpolate(x3, x2, opt.minV, opt.maxV);
- var bottomleft = opt.interpolate(x0, x1, opt.minV, opt.maxV);
- if (opt.polygons_full) {
- cell.edges.tl = {
- path: [ [topleft, 1], [bottomleft, 0] ],
- move: {
- x: 0,
- y: -1,
- enter: 'tl'
- }
- };
- }
- if (opt.polygons)
- cell.polygons.push([ [0, 0], [0, 1], [topleft, 1], [bottomleft, 0] ]);
- },
- tetragon_bl: function(cell, x0, x1, x2, x3, opt) {
- var bottomleft = opt.interpolate_a(x0, x1, opt.minV, opt.maxV);
- var bottomright = opt.interpolate_b(x0, x1, opt.minV, opt.maxV);
- var leftbottom = opt.interpolate_a(x0, x3, opt.minV, opt.maxV);
- var lefttop = opt.interpolate_b(x0, x3, opt.minV, opt.maxV);
- if (opt.polygons_full) {
- cell.edges.bl = {
- path: [ [bottomleft, 0], [0, leftbottom] ],
- move: {
- x: -1,
- y: 0,
- enter: 'rb'
- }
- };
- cell.edges.lt = {
- path: [ [0, lefttop], [bottomright, 0] ],
- move: {
- x: 0,
- y: -1,
- enter: 'tr'
- }
- };
- }
- if (opt.polygons)
- cell.polygons.push([ [bottomleft, 0], [0, leftbottom], [0, lefttop], [bottomright, 0] ]);
- },
- tetragon_br: function(cell, x0, x1, x2, x3, opt) {
- var bottomleft = opt.interpolate_a(x0, x1, opt.minV, opt.maxV);
- var bottomright = opt.interpolate_b(x0, x1, opt.minV, opt.maxV);
- var rightbottom = opt.interpolate_a(x1, x2, opt.minV, opt.maxV);
- var righttop = opt.interpolate_b(x1, x2, opt.minV, opt.maxV);
- if (opt.polygons_full) {
- cell.edges.bl = {
- path: [ [bottomleft, 0], [1, righttop] ],
- move: {
- x: 1,
- y: 0,
- enter: 'lt'
- }
- };
- cell.edges.rb = {
- path: [ [1, rightbottom], [bottomright, 0] ],
- move: {
- x: 0,
- y: -1,
- enter: 'tr'
- }
- };
- }
- if (opt.polygons)
- cell.polygons.push([ [bottomleft, 0], [1, righttop], [1, rightbottom], [bottomright, 0] ]);
- },
- tetragon_tr: function(cell, x0, x1, x2, x3, opt) {
- var topleft = opt.interpolate_a(x3, x2, opt.minV, opt.maxV);
- var topright = opt.interpolate_b(x3, x2, opt.minV, opt.maxV);
- var righttop = opt.interpolate_b(x1, x2, opt.minV, opt.maxV);
- var rightbottom = opt.interpolate_a(x1, x2, opt.minV, opt.maxV);
- if (opt.polygons_full) {
- cell.edges.rb = {
- path: [ [1, rightbottom], [topleft, 1] ],
- move: {
- x: 0,
- y: 1,
- enter: 'bl'
- }
- };
- cell.edges.tr = {
- path: [ [topright, 1], [1, righttop] ],
- move: {
- x: 1,
- y: 0,
- enter: 'lt'
- }
- };
- }
- if (opt.polygons)
- cell.polygons.push([ [1, rightbottom], [topleft, 1], [topright, 1], [1, righttop] ]);
- },
- tetragon_tl: function(cell, x0, x1, x2, x3, opt) {
- var topleft = opt.interpolate_a(x3, x2, opt.minV, opt.maxV);
- var topright = opt.interpolate_b(x3, x2, opt.minV, opt.maxV);
- var lefttop = opt.interpolate_b(x0, x3, opt.minV, opt.maxV);
- var leftbottom = opt.interpolate_a(x0, x3, opt.minV, opt.maxV);
- if (opt.polygons_full) {
- cell.edges.tr = {
- path: [ [topright, 1], [0, leftbottom] ],
- move: {
- x: -1,
- y: 0,
- enter: 'rb'
- }
- };
- cell.edges.lt = {
- path: [ [0, lefttop], [topleft, 1] ],
- move: {
- x: 0,
- y: 1,
- enter: 'bl'
- }
- };
- }
- if (opt.polygons)
- cell.polygons.push([ [topright, 1], [0, leftbottom], [0, lefttop], [topleft, 1] ]);
- },
- tetragon_lr: function(cell, x0, x1, x2, x3, opt) {
- var leftbottom = opt.interpolate_a(x0, x3, opt.minV, opt.maxV);
- var lefttop = opt.interpolate_b(x0, x3, opt.minV, opt.maxV);
- var righttop = opt.interpolate_b(x1, x2, opt.minV, opt.maxV);
- var rightbottom = opt.interpolate_a(x1, x2, opt.minV, opt.maxV);
- if (opt.polygons_full) {
- cell.edges.lt = {
- path: [ [0, lefttop], [1, righttop] ],
- move: {
- x: 1,
- y: 0,
- enter: 'lt'
- }
- };
- cell.edges.rb = {
- path: [ [1, rightbottom], [0, leftbottom] ],
- move: {
- x: -1,
- y: 0,
- enter: 'rb'
- }
- };
- }
- if (opt.polygons)
- cell.polygons.push([ [0, leftbottom], [0, lefttop], [1, righttop], [1, rightbottom] ]);
- },
- tetragon_tb: function(cell, x0, x1, x2, x3, opt) {
- var topleft = opt.interpolate_a(x3, x2, opt.minV, opt.maxV);
- var topright = opt.interpolate_b(x3, x2, opt.minV, opt.maxV);
- var bottomright = opt.interpolate_b(x0, x1, opt.minV, opt.maxV);
- var bottomleft = opt.interpolate_a(x0, x1, opt.minV, opt.maxV);
- if (opt.polygons_full) {
- cell.edges.tr = {
- path: [ [topright, 1], [bottomright, 0] ],
- move: {
- x: 0,
- y: -1,
- enter: 'tr'
- }
- };
- cell.edges.bl = {
- path: [ [bottomleft, 0], [topleft, 1] ],
- move: {
- x: 0,
- y: 1,
- enter: 'bl'
- }
- };
- }
- if (opt.polygons)
- cell.polygons.push([ [bottomleft, 0], [topleft, 1], [topright, 1], [bottomright, 0] ]);
- },
- pentagon_tr: function(cell, x0, x1, x2, x3, opt) {
- var topleft = opt.interpolate(x3, x2, opt.minV, opt.maxV);
- var rightbottom = opt.interpolate(x1, x2, opt.minV, opt.maxV);
- if (opt.polygons_full) {
- cell.edges.tl = {
- path: [[topleft, 1], [1, rightbottom]],
- move: {
- x: 1,
- y: 0,
- enter: 'lb'
- }
- };
- }
- if (opt.polygons)
- cell.polygons.push([ [0, 0], [0, 1], [topleft, 1], [1, rightbottom], [1, 0] ]);
- },
- pentagon_tl: function(cell, x0, x1, x2, x3, opt) {
- var leftbottom = opt.interpolate(x0, x3, opt.minV, opt.maxV);
- var topright = opt.interpolate(x3, x2, opt.minV, opt.maxV);
- if (opt.polygons_full) {
- cell.edges.lb = {
- path: [ [0, leftbottom], [topright, 1] ],
- move: {
- x: 0,
- y: 1,
- enter: 'br'
- }
- };
- }
- if (opt.polygons)
- cell.polygons.push([ [0, 0], [0, leftbottom], [topright, 1], [1, 1], [1, 0] ]);
- },
- pentagon_br: function(cell, x0, x1, x2, x3, opt) {
- var bottomleft = opt.interpolate(x0, x1, opt.minV, opt.maxV);
- var righttop = opt.interpolate(x1, x2, opt.minV, opt.maxV);
- if (opt.polygons_full) {
- cell.edges.rt = {
- path: [ [1, righttop], [bottomleft, 0] ],
- move: {
- x: 0,
- y: -1,
- enter: 'tl'
- }
- };
- }
- if (opt.polygons)
- cell.polygons.push([ [0, 0], [0, 1], [1, 1], [1, righttop], [bottomleft, 0] ]);
- },
- pentagon_bl: function(cell, x0, x1, x2, x3, opt) {
- var lefttop = opt.interpolate(x0, x3, opt.minV, opt.maxV);
- var bottomright = opt.interpolate(x0, x1, opt.minV, opt.maxV);
- if (opt.polygons_full) {
- cell.edges.br = {
- path: [ [bottomright, 0], [0, lefttop] ],
- move: {
- x: -1,
- y: 0,
- enter: 'rt'
- }
- };
- }
- if (opt.polygons)
- cell.polygons.push([ [0, lefttop], [0, 1], [1, 1], [1, 0], [bottomright, 0] ]);
- },
- pentagon_tr_rl: function(cell, x0, x1, x2, x3, opt) {
- var lefttop = opt.interpolate(x0, x3, opt.minV, opt.maxV);
- var topleft = opt.interpolate(x3, x2, opt.minV, opt.maxV);
- var righttop = opt.interpolate_b(x1, x2, opt.minV, opt.maxV);
- var rightbottom = opt.interpolate_a(x1, x2, opt.minV, opt.maxV);
- if (opt.polygons_full) {
- cell.edges.tl = {
- path: [ [topleft, 1], [1, righttop] ],
- move: {
- x: 1,
- y: 0,
- enter: 'lt'
- }
- };
- cell.edges.rb = {
- path: [ [1, rightbottom], [0, lefttop] ],
- move: {
- x: -1,
- y: 0,
- enter: 'rt'
- }
- };
- }
- if (opt.polygons)
- cell.polygons.push([ [0, lefttop], [0, 1], [topleft, 1], [1, righttop], [1, rightbottom] ]);
- },
- pentagon_rb_bt: function(cell, x0, x1, x2, x3, opt) {
- var righttop = opt.interpolate(x1, x2, opt.minV, opt.maxV);
- var bottomright = opt.interpolate_b(x0, x1, opt.minV, opt.maxV);
- var bottomleft = opt.interpolate_a(x0, x1, opt.minV, opt.maxV);
- var topright = opt.interpolate(x3, x2, opt.minV, opt.maxV);
- if (opt.polygons_full) {
- cell.edges.rt = {
- path: [ [1, righttop], [bottomright, 0] ],
- move: {
- x: 0,
- y: -1,
- enter: 'tr'
- }
- };
- cell.edges.bl = {
- path: [ [bottomleft, 0], [topright, 1] ],
- move: {
- x: 0,
- y: 1,
- enter: 'br'
- }
- };
- }
- if (opt.polygons)
- cell.polygons.push([ [topright, 1], [1, 1], [1, righttop], [bottomright, 0], [bottomleft, 0] ]);
- },
- pentagon_bl_lr: function(cell, x0, x1, x2, x3, opt) {
- var bottomright = opt.interpolate(x0, x1, opt.minV, opt.maxV);
- var leftbottom = opt.interpolate_a(x0, x3, opt.minV, opt.maxV);
- var lefttop = opt.interpolate_b(x0, x3, opt.minV, opt.maxV);
- var rightbottom = opt.interpolate(x1, x2, opt.minV, opt.maxV);
- if (opt.polygons_full) {
- cell.edges.br = {
- path: [ [bottomright, 0], [0, leftbottom] ],
- move: {
- x: -1,
- y: 0,
- enter: 'rb'
- }
- };
- cell.edges.lt = {
- path: [ [0, lefttop], [1, rightbottom] ],
- move: {
- x: 1,
- y: 0,
- enter: 'lb'
- }
- };
- }
- if (opt.polygons)
- cell.polygons.push([ [bottomright, 0], [0, leftbottom], [0, lefttop], [1, rightbottom], [1, 0] ]);
- },
- pentagon_lt_tb: function(cell, x0, x1, x2, x3, opt) {
- var leftbottom = opt.interpolate(x0, x3, opt.minV, opt.maxV);
- var topleft = opt.interpolate_a(x3, x2, opt.minV, opt.maxV);
- var topright = opt.interpolate_b(x3, x2, opt.minV, opt.maxV);
- var bottomleft = opt.interpolate(x0, x1, opt.minV, opt.maxV);
- if (opt.polygons_full) {
- cell.edges.lb = {
- path: [ [0, leftbottom], [topleft, 1] ],
- move: {
- x: 0,
- y: 1,
- enter: 'bl'
- }
- };
- cell.edges.tr = {
- path: [ [topright, 1], [bottomleft, 0] ],
- move: {
- x: 0,
- y: -1,
- enter: 'tl'
- }
- };
- }
- if (opt.polygons)
- cell.polygons.push([ [0, 0], [0, leftbottom], [topleft, 1], [topright, 1], [bottomleft, 0] ]);
- },
- pentagon_bl_tb: function(cell, x0, x1, x2, x3, opt) {
- var lefttop = opt.interpolate(x0, x3, opt.minV, opt.maxV);
- var topleft = opt.interpolate(x3, x2, opt.minV, opt.maxV);
- var bottomright = opt.interpolate_b(x0, x1, opt.minV, opt.maxV);
- var bottomleft = opt.interpolate_a(x0, x1, opt.minV, opt.maxV);
- if (opt.polygons_full) {
- cell.edges.bl = {
- path: [ [bottomleft, 0], [0, lefttop] ],
- move: {
- x: -1,
- y: 0,
- enter: 'rt'
- }
- };
- cell.edges.tl = {
- path: [ [ topleft, 1], [bottomright, 0] ],
- move: {
- x: 0,
- y: -1,
- enter: 'tr'
- }
- };
- }
- if (opt.polygons)
- cell.polygons.push([ [0, lefttop], [0, 1], [topleft, 1], [bottomright, 0], [bottomleft, 0] ]);
- },
- pentagon_lt_rl: function(cell, x0, x1, x2, x3, opt) {
- var leftbottom = opt.interpolate_a(x0, x3, opt.minV, opt.maxV);
- var lefttop = opt.interpolate_b(x0, x3, opt.minV, opt.maxV);
- var topright = opt.interpolate(x3, x2, opt.minV, opt.maxV);
- var righttop = opt.interpolate(x1, x3, opt.minV, opt.maxV);
- if (opt.polygons_full) {
- cell.edges.lt = {
- path: [ [0, lefttop], [topright, 1] ],
- move: {
- x: 0,
- y: 1,
- enter: 'br'
- }
- };
- cell.edges.rt = {
- path: [ [1, righttop], [0, leftbottom] ],
- move: {
- x: -1,
- y: 0,
- enter: 'rb'
- }
- };
- }
- if (opt.polygons)
- cell.polygons.push([ [0, leftbottom], [0, lefttop], [topright, 1], [1, 1], [1, righttop] ]);
- },
- pentagon_tr_bt: function(cell, x0, x1, x2, x3, opt) {
- var topleft = opt.interpolate_a(x3, x2, opt.minV, opt.maxV);
- var topright = opt.interpolate_b(x3, x2, opt.minV, opt.maxV);
- var rightbottom = opt.interpolate(x1, x2, opt.minV, opt.maxV);
- var bottomright = opt.interpolate(x0, x1, opt.minV, opt.maxV);
- if (opt.polygons_full) {
- cell.edges.br = {
- path: [ [bottomright, 0], [topleft, 1] ],
- move: {
- x: 0,
- y: 1,
- enter: 'bl'
- }
- };
- cell.edges.tr = {
- path: [ [topright, 1], [1, rightbottom] ],
- move: {
- x: 1,
- y: 0,
- enter: 'lb'
- }
- };
- }
- if (opt.polygons)
- cell.polygons.push([ [topleft, 1], [topright, 1], [1, rightbottom], [1, 0], [bottomright, 0] ]);
- },
- pentagon_rb_lr: function(cell, x0, x1, x2, x3, opt) {
- var leftbottom = opt.interpolate(x0, x3, opt.minV, opt.maxV);
- var righttop = opt.interpolate_b(x1, x2, opt.minV, opt.maxV);
- var rightbottom = opt.interpolate_a(x1, x2, opt.minV, opt.maxV);
- var bottomleft = opt.interpolate(x0, x1, opt.minV, opt.maxV);
- if (opt.polygons_full) {
- cell.edges.lb = {
- path: [ [0, leftbottom], [1, righttop] ],
- move: {
- x: 1,
- y: 0,
- enter: 'lt'
- }
- };
- cell.edges.rb = {
- path: [ [1, rightbottom], [bottomleft, 0] ],
- move: {
- x: 0,
- y: -1,
- enter: 'tl'
- }
- };
- }
- if (opt.polygons)
- cell.polygons.push([ [0, 0], [0, leftbottom], [1, righttop], [1, rightbottom], [bottomleft, 0] ]);
- },
- hexagon_lt_tr: function(cell, x0, x1, x2, x3, opt) {
- var leftbottom = opt.interpolate(x0, x3, opt.minV, opt.maxV);
- var topleft = opt.interpolate_a(x3, x2, opt.minV, opt.maxV);
- var topright = opt.interpolate_b(x3, x2, opt.minV, opt.maxV);
- var rightbottom = opt.interpolate(x1, x2, opt.minV, opt.maxV);
- if (opt.polygons_full) {
- cell.edges.lb = {
- path: [ [0, leftbottom], [topleft, 1] ],
- move: {
- x: 0,
- y: 1,
- enter: 'bl'
- }
- };
- cell.edges.tr = {
- path: [ [topright, 1], [1, rightbottom] ],
- move: {
- x: 1,
- y: 0,
- enter: 'lb'
- }
- };
- }
- if (opt.polygons)
- cell.polygons.push([ [0, 0], [0, leftbottom], [topleft, 1], [topright, 1], [1, rightbottom], [1, 0] ]);
- },
- hexagon_bl_lt: function(cell, x0, x1, x2, x3, opt) {
- var bottomright = opt.interpolate(x0, x1, opt.minV, opt.maxV);
- var leftbottom = opt.interpolate_a(x0, x3, opt.minV, opt.maxV);
- var lefttop = opt.interpolate_b(x0, x3, opt.minV, opt.maxV);
- var topright = opt.interpolate(x3, x2, opt.minV, opt.maxV);
- if (opt.polygons_full) {
- cell.edges.br = {
- path: [ [bottomright, 0], [0, leftbottom] ],
- move: {
- x: -1,
- y: 0,
- enter: 'rb'
- }
- };
- cell.edges.lt = {
- path: [ [0, lefttop], [topright, 1] ],
- move: {
- x: 0,
- y: 1,
- enter: 'br'
- }
- };
- }
- if (opt.polygons)
- cell.polygons.push([ [bottomright, 0], [0, leftbottom], [0, lefttop], [topright, 1], [1, 1], [1, 0] ]);
- },
- hexagon_bl_rb: function(cell, x0, x1, x2, x3, opt) {
- var bottomleft = opt.interpolate_a(x0, x1, opt.minV, opt.maxV);
- var bottomright = opt.interpolate_b(x0, x1, opt.minV, opt.maxV);
- var lefttop = opt.interpolate(x0, x3, opt.minV, opt.maxV);
- var righttop = opt.interpolate(x1, x2, opt.minV, opt.maxV);
- if (opt.polygons_full) {
- cell.edges.bl = {
- path: [ [bottomleft, 0], [0, lefttop] ],
- move: {
- x: -1,
- y: 0,
- enter: 'rt'
- }
- };
- cell.edges.rt = {
- path: [ [1, righttop], [bottomright, 0] ],
- move: {
- x: 0,
- y: -1,
- enter: 'tr'
- }
- };
- }
- if (opt.polygons)
- cell.polygons.push([ [bottomleft, 0], [0, lefttop], [0, 1], [1, 1], [1, righttop], [bottomright, 0] ]);
- },
- hexagon_tr_rb: function(cell, x0, x1, x2, x3, opt) {
- var bottomleft = opt.interpolate(x0, x1, opt.minV, opt.maxV);
- var topleft = opt.interpolate(x3, x2, opt.minV, opt.maxV);
- var righttop = opt.interpolate_b(x1, x2, opt.minV, opt.maxV);
- var rightbottom = opt.interpolate_a(x1, x2, opt.minV, opt.maxV);
- if (opt.polygons_full) {
- cell.edges.tl = {
- path: [ [topleft, 1], [1, righttop] ],
- move: {
- x: 1,
- y: 0,
- enter: 'lt'
- }
- };
- cell.edges.rb = {
- path: [ [1, rightbottom], [bottomleft, 0] ],
- move: {
- x: 0,
- y: -1,
- enter: 'tl'
- }
- };
- }
- if (opt.polygons)
- cell.polygons.push([ [0, 0], [0, 1], [topleft, 1], [1, righttop], [1, rightbottom], [bottomleft, 0] ]);
- },
- hexagon_lt_rb: function(cell, x0, x1, x2, x3, opt) {
- var leftbottom = opt.interpolate(x0, x3, opt.minV, opt.maxV);
- var topright = opt.interpolate(x3, x2, opt.minV, opt.maxV);
- var righttop = opt.interpolate(x1, x2, opt.minV, opt.maxV);
- var bottomleft = opt.interpolate(x0, x1, opt.minV, opt.maxV);
- if (opt.polygons_full) {
- cell.edges.lb = {
- path: [ [0, leftbottom], [topright, 1] ],
- move: {
- x: 0,
- y: 1,
- enter: 'br'
- }
- };
- cell.edges.rt = {
- path: [ [1, righttop], [bottomleft, 0] ],
- move: {
- x: 0,
- y: -1,
- enter: 'tl'
- }
- };
- }
- if (opt.polygons)
- cell.polygons.push([ [0, 0], [0, leftbottom], [topright, 1], [1, 1], [1, righttop], [bottomleft, 0] ]);
- },
- hexagon_bl_tr: function(cell, x0, x1, x2, x3, opt) {
- var bottomright = opt.interpolate(x0, x1, opt.minV, opt.maxV);
- var lefttop = opt.interpolate(x0, x3, opt.minV, opt.maxV);
- var topleft = opt.interpolate(x3, x2, opt.minV, opt.maxV);
- var rightbottom = opt.interpolate(x1, x2, opt.minV, opt.maxV);
- if (opt.polygons_full) {
- cell.edges.br = {
- path: [ [bottomright, 0], [0, lefttop] ],
- move: {
- x: -1,
- y: 0,
- enter: 'rt'
- }
- };
- cell.edges.tl = {
- path: [ [topleft, 1], [1, rightbottom] ],
- move: {
- x: 1,
- y: 0,
- enter: 'lb'
- }
- };
- }
- if (opt.polygons)
- cell.polygons.push([ [bottomright, 0], [0, lefttop], [0, 1], [topleft, 1], [1, rightbottom], [1, 0] ]);
- },
- heptagon_tr: function(cell, x0, x1, x2, x3, opt) {
- var bottomleft = opt.interpolate_a(x0, x1, opt.minV, opt.maxV);
- var bottomright = opt.interpolate_b(x0, x1, opt.minV, opt.maxV);
- var leftbottom = opt.interpolate_a(x0, x3, opt.minV, opt.maxV);
- var lefttop = opt.interpolate_b(x0, x3, opt.minV, opt.maxV);
- var topright = opt.interpolate(x3, x2, opt.minV, opt.maxV);
- var righttop = opt.interpolate(x1, x2, opt.minV, opt.maxV);
- if (opt.polygons_full) {
- cell.edges.bl = {
- path: [ [bottomleft, 0], [0, leftbottom] ],
- move: {
- x: -1,
- y: 0,
- enter: 'rb'
- }
- };
- cell.edges.lt = {
- path: [ [0, lefttop], [topright, 1] ],
- move: {
- x: 0,
- y: 1,
- enter: 'br'
- }
- };
- cell.edges.rt = {
- path: [ [1, righttop], [bottomright, 0] ],
- move: {
- x: 0,
- y: -1,
- enter: 'tr'
- }
- };
- }
- if (opt.polygons)
- cell.polygons.push([ [bottomleft, 0], [0, leftbottom], [0, lefttop], [topright, 1], [1, 1], [1, righttop], [bottomright, 0] ]);
- },
- heptagon_bl: function(cell, x0, x1, x2, x3, opt) {
- var bottomleft = opt.interpolate(x0, x1, opt.minV, opt.maxV);
- var leftbottom = opt.interpolate(x0, x3, opt.minV, opt.maxV);
- var topleft = opt.interpolate_a(x3, x2, opt.minV, opt.maxV);
- var topright = opt.interpolate_b(x3, x2, opt.minV, opt.maxV);
- var righttop = opt.interpolate_b(x1, x2, opt.minV, opt.maxV);
- var rightbottom = opt.interpolate_a(x1, x2, opt.minV, opt.maxV);
- if (opt.polygons_full) {
- cell.edges.lb = {
- path: [ [0, leftbottom], [topleft, 1] ],
- move: {
- x: 0,
- y: 1,
- enter: 'bl'
- }
- };
- cell.edges.tr = {
- path: [ [topright, 1], [1, righttop] ],
- move: {
- x: 1,
- y: 0,
- enter: 'lt'
- }
- };
- cell.edges.rb = {
- path: [ [1, rightbottom], [bottomleft, 0] ],
- move: {
- x: 0,
- y: -1,
- enter: 'tl'
- }
- };
- }
- if (opt.polygons)
- cell.polygons.push([ [0, 0], [0, leftbottom], [topleft, 1], [topright, 1], [1, righttop], [1, rightbottom], [bottomleft, 0] ]);
- },
- heptagon_tl: function(cell, x0, x1, x2, x3, opt) {
- var bottomleft = opt.interpolate_a(x0, x1, opt.minV, opt.maxV);
- var bottomright = opt.interpolate_b(x0, x1, opt.minV, opt.maxV);
- var lefttop = opt.interpolate(x0, x3, opt.minV, opt.maxV);
- var topleft = opt.interpolate(x3, x2, opt.minV, opt.maxV);
- var righttop = opt.interpolate_b(x1, x2, opt.minV, opt.maxV);
- var rightbottom = opt.interpolate_a(x1, x2, opt.minV, opt.maxV);
- if (opt.polygons_full) {
- cell.edges.bl = {
- path: [ [bottomleft, 0], [0, lefttop] ],
- move: {
- x: -1,
- y: 0,
- enter: 'rt'
- }
- };
- cell.edges.tl = {
- path: [ [topleft, 1], [1, righttop] ],
- move: {
- x: 1,
- y: 0,
- enter: 'lt'
- }
- };
- cell.edges.rb = {
- path: [ [1, rightbottom], [bottomright, 0] ],
- move: {
- x: 0,
- y: -1,
- enter: 'tr'
- }
- };
- }
- if (opt.polygons)
- cell.polygons.push([ [bottomleft, 0], [0, lefttop], [0, 1], [topleft, 1], [1, righttop], [1, rightbottom], [bottomright, 0] ]);
- },
- heptagon_br: function(cell, x0, x1, x2, x3, opt) {
- var bottomright = opt.interpolate(x0, x1, opt.minV, opt.maxV);
- var leftbottom = opt.interpolate_a(x0, x3, opt.minV, opt.maxV);
- var lefttop = opt.interpolate_b(x0, x3, opt.minV, opt.maxV);
- var topleft = opt.interpolate_a(x3, x2, opt.minV, opt.maxV);
- var topright = opt.interpolate_b(x3, x2, opt.minV, opt.maxV);
- var rightbottom = opt.interpolate(x1, x2, opt.minV, opt.maxV);
- if (opt.polygons_full) {
- cell.edges.br = {
- path: [ [bottomright, 0], [0, leftbottom] ],
- move: {
- x: -1,
- y: 0,
- enter: 'rb'
- }
- };
- cell.edges.lt = {
- path: [ [0, lefttop], [topleft, 1] ],
- move: {
- x: 0,
- y: 1,
- enter: 'bl'
- }
- };
- cell.edges.tr = {
- path: [ [topright, 1], [1, rightbottom] ],
- move: {
- x: 1,
- y: 0,
- enter: 'lb'
- }
- };
- }
- if (opt.polygons)
- cell.polygons.push([ [bottomright,0], [0, leftbottom], [0, lefttop], [topleft, 1], [topright, 1], [1, rightbottom], [1, 0] ]);
- },
- octagon: function(cell, x0, x1, x2, x3, opt) {
- var bottomleft = opt.interpolate_a(x0, x1, opt.minV, opt.maxV);
- var bottomright = opt.interpolate_b(x0, x1, opt.minV, opt.maxV);
- var leftbottom = opt.interpolate_a(x0, x3, opt.minV, opt.maxV);
- var lefttop = opt.interpolate_b(x0, x3, opt.minV, opt.maxV);
- var topleft = opt.interpolate_a(x3, x2, opt.minV, opt.maxV);
- var topright = opt.interpolate_b(x3, x2, opt.minV, opt.maxV);
- var righttop = opt.interpolate_b(x1, x2, opt.minV, opt.maxV);
- var rightbottom = opt.interpolate_a(x1, x2, opt.minV, opt.maxV);
- if (opt.polygons_full) {
- cell.edges.bl = {
- path: [ [bottomleft, 0], [0, leftbottom] ],
- move: {
- x: -1,
- y: 0,
- enter: 'rb'
- }
- };
- cell.edges.lt = {
- path: [ [0, lefttop], [topleft, 1] ],
- move: {
- x: 0,
- y: 1,
- enter: 'bl'
- }
- };
- cell.edges.tr = {
- path: [ [topright, 1], [1, righttop] ],
- move: {
- x: 1,
- y: 0,
- enter: 'lt'
- }
- };
- cell.edges.rb = {
- path: [ [1, rightbottom], [bottomright, 0] ],
- move: {
- x: 0,
- y: -1,
- enter: 'tr'
- }
- };
- }
- if (opt.polygons)
- cell.polygons.push([ [bottomleft, 0], [0, leftbottom], [0, lefttop], [topleft, 1], [topright, 1], [1, righttop], [1, rightbottom], [bottomright, 0] ]);
- }
- };
- /*
- * Compute isobands(s) for a scalar 2D field given a certain
- * threshold and a bandwidth by applying the Marching Squares
- * Algorithm. The function returns a list of path coordinates
- * either for individual polygons within each grid cell, or the
- * outline of connected polygons.
- */
- function isoBands(input, minV, bandWidth, options) {
- var i,
- j,
- settings,
- useQuadTree = false,
- tree = null,
- root = null,
- data = null,
- cellGrid = null,
- multiBand = false,
- bw = [],
- bandPolygons = [],
- ret = [];
- /* basic input validation */
- if (!input) throw new Error('data is required');
- if (minV === undefined || minV === null) throw new Error('lowerBound is required');
- if (bandWidth === undefined || bandWidth === null) throw new Error('bandWidth is required');
- if ((!!options) && (typeof options !== 'object')) throw new Error('options must be an object');
- settings = isoBandOptions(options);
- /* check for input data */
- if (input instanceof QuadTree) {
- tree = input;
- root = input.root;
- data = input.data;
- if (!settings.noQuadTree)
- useQuadTree = true;
- } else if (Array.isArray(input) && Array.isArray(input[0])) {
- data = input;
- } else {
- throw new Error('input is neither array of arrays nor object retrieved from \'QuadTree()\'');
- }
- /* check and prepare input thresholds */
- if (Array.isArray(minV)) {
- multiBand = true;
- /* activate QuadTree optimization if not explicitly forbidden by user settings */
- if (!settings.noQuadTree)
- useQuadTree = true;
- /* check if all minV are numbers */
- for (i = 0; i < minV.length; i++)
- if (isNaN(+minV[i]))
- throw new Error('lowerBound[' + i + '] is not a number');
- if (Array.isArray(bandWidth)) {
- if (minV.length !== bandWidth.length)
- throw new Error('lowerBound and bandWidth have unequal lengths');
- /* check bandwidth values */
- for (i = 0; i < bandWidth.length; i++)
- if (isNaN(+bandWidth[i]))
- throw new Error('bandWidth[' + i + '] is not a number');
- } else {
- if (isNaN(+bandWidth))
- throw new Error('bandWidth must be a number');
- bw = [];
- for (i = 0; i < minV.length; i++) {
- bw.push(bandWidth);
- }
- bandWidth = bw;
- }
- } else {
- if (isNaN(+minV))
- throw new Error('lowerBound must be a number');
- minV = [ minV ];
- if (isNaN(+bandWidth))
- throw new Error('bandWidth must be a number');
- bandWidth = [ bandWidth ];
- }
- /* create QuadTree root node if not already present */
- if ((useQuadTree) && (!root)) {
- tree = new QuadTree(data);
- root = tree.root;
- data = tree.data;
- }
- if (settings.verbose) {
- if(settings.polygons)
- console.log('MarchingSquaresJS-isoBands: returning single polygons for each grid cell');
- else
- console.log('MarchingSquaresJS-isoBands: returning polygon paths for entire data grid');
- if (multiBand)
- console.log('MarchingSquaresJS-isoBands: multiple bands requested, returning array of band polygons instead of polygons for a single band');
- }
- /* Done with all input validation, now let's start computing stuff */
- /* loop over all minV values */
- minV.forEach(function(lowerBound, b) {
- bandPolygons = [];
- /* store bounds for current computation in settings object */
- settings.minV = lowerBound;
- settings.maxV = lowerBound + bandWidth[b];
- if(settings.verbose)
- console.log('MarchingSquaresJS-isoBands: computing isobands for [' + lowerBound + ':' + (lowerBound + bandWidth[b]) + ']');
- if (settings.polygons) {
- /* compose list of polygons for each single cell */
- if (useQuadTree) {
- /* go through list of cells retrieved from QuadTree */
- root
- .cellsInBand(settings.minV, settings.maxV, true)
- .forEach(function(c) {
- bandPolygons = bandPolygons.concat(
- cell2Polygons(
- prepareCell$1(data,
- c.x,
- c.y,
- settings),
- c.x,
- c.y,
- settings
- ));
- });
- } else {
- /* go through entire array of input data */
- for (j = 0; j < data.length - 1; ++j) {
- for (i = 0; i < data[0].length - 1; ++i)
- bandPolygons = bandPolygons.concat(
- cell2Polygons(
- prepareCell$1(data,
- i,
- j,
- settings),
- i,
- j,
- settings
- ));
- }
- }
- } else {
- /* sparse grid of input data cells */
- cellGrid = [];
- for (i = 0; i < data[0].length - 1; ++i)
- cellGrid[i] = [];
- /* compose list of polygons for entire input grid */
- if (useQuadTree) {
- /* collect the cells */
- root
- .cellsInBand(settings.minV, settings.maxV, false)
- .forEach(function(c) {
- cellGrid[c.x][c.y] = prepareCell$1(data,
- c.x,
- c.y,
- settings);
- });
- } else {
- /* prepare cells */
- for (i = 0; i < data[0].length - 1; ++i) {
- for (j = 0; j < data.length - 1; ++j) {
- cellGrid[i][j] = prepareCell$1(data,
- i,
- j,
- settings);
- }
- }
- }
- bandPolygons = traceBandPaths(data, cellGrid, settings);
- }
- /* finally, add polygons to output array */
- if (multiBand)
- ret.push(bandPolygons);
- else
- ret = bandPolygons;
- if(typeof settings.successCallback === 'function')
- settings.successCallback(ret, lowerBound, bandWidth[b]);
- });
- return ret;
- }
- /*
- * Thats all for the public interface, below follows the actual
- * implementation
- */
- /*
- * For isoBands, each square is defined by the three states
- * of its corner points. However, since computers use power-2
- * values, we use 2bits per trit, i.e.:
- *
- * 00 ... below minV
- * 01 ... between minV and maxV
- * 10 ... above maxV
- *
- * Hence we map the 4-trit configurations as follows:
- *
- * 0000 => 0
- * 0001 => 1
- * 0002 => 2
- * 0010 => 4
- * 0011 => 5
- * 0012 => 6
- * 0020 => 8
- * 0021 => 9
- * 0022 => 10
- * 0100 => 16
- * 0101 => 17
- * 0102 => 18
- * 0110 => 20
- * 0111 => 21
- * 0112 => 22
- * 0120 => 24
- * 0121 => 25
- * 0122 => 26
- * 0200 => 32
- * 0201 => 33
- * 0202 => 34
- * 0210 => 36
- * 0211 => 37
- * 0212 => 38
- * 0220 => 40
- * 0221 => 41
- * 0222 => 42
- * 1000 => 64
- * 1001 => 65
- * 1002 => 66
- * 1010 => 68
- * 1011 => 69
- * 1012 => 70
- * 1020 => 72
- * 1021 => 73
- * 1022 => 74
- * 1100 => 80
- * 1101 => 81
- * 1102 => 82
- * 1110 => 84
- * 1111 => 85
- * 1112 => 86
- * 1120 => 88
- * 1121 => 89
- * 1122 => 90
- * 1200 => 96
- * 1201 => 97
- * 1202 => 98
- * 1210 => 100
- * 1211 => 101
- * 1212 => 102
- * 1220 => 104
- * 1221 => 105
- * 1222 => 106
- * 2000 => 128
- * 2001 => 129
- * 2002 => 130
- * 2010 => 132
- * 2011 => 133
- * 2012 => 134
- * 2020 => 136
- * 2021 => 137
- * 2022 => 138
- * 2100 => 144
- * 2101 => 145
- * 2102 => 146
- * 2110 => 148
- * 2111 => 149
- * 2112 => 150
- * 2120 => 152
- * 2121 => 153
- * 2122 => 154
- * 2200 => 160
- * 2201 => 161
- * 2202 => 162
- * 2210 => 164
- * 2211 => 165
- * 2212 => 166
- * 2220 => 168
- * 2221 => 169
- * 2222 => 170
- */
- /*
- * ####################################
- * Some small helper functions
- * ####################################
- */
- function computeCenterAverage(bl, br, tr, tl, minV, maxV) {
- var average = (tl + tr + br + bl) / 4;
- if (average > maxV)
- return 2; /* above isoband limits */
- if (average < minV)
- return 0; /* below isoband limits */
- return 1; /* within isoband limits */
- }
- function prepareCell$1(grid, x, y, opt) {
- var cell,
- center_avg;
- /* compose the 4-trit corner representation */
- var cval = 0;
- var x3 = grid[y + 1][x];
- var x2 = grid[y + 1][x + 1];
- var x1 = grid[y][x + 1];
- var x0 = grid[y][x];
- var minV = opt.minV;
- var maxV = opt.maxV;
- /*
- * Note that missing data within the grid will result
- * in horribly failing to trace full polygon paths
- */
- if(isNaN(x0) || isNaN(x1) || isNaN(x2) || isNaN(x3)) {
- return;
- }
- /*
- * Here we detect the type of the cell
- *
- * x3 ---- x2
- * | |
- * | |
- * x0 ---- x1
- *
- * with edge points
- *
- * x0 = (x,y),
- * x1 = (x + 1, y),
- * x2 = (x + 1, y + 1), and
- * x3 = (x, y + 1)
- *
- * and compute the polygon intersections with the edges
- * of the cell. Each edge value may be (i) below, (ii) within,
- * or (iii) above the values of the isoband limits. We
- * encode this property using 2 bits of information, where
- *
- * 00 ... below,
- * 01 ... within, and
- * 10 ... above
- *
- * Then we store the cells value as vector
- *
- * cval = (x0, x1, x2, x3)
- *
- * where x0 are the two least significant bits (0th, 1st),
- * x1 the 2nd and 3rd bit, and so on. This essentially
- * enables us to work with a single integer number
- */
- cval |= (x3 < minV) ? 0 : (x3 > maxV) ? 128 : 64;
- cval |= (x2 < minV) ? 0 : (x2 > maxV) ? 32 : 16;
- cval |= (x1 < minV) ? 0 : (x1 > maxV) ? 8 : 4;
- cval |= (x0 < minV) ? 0 : (x0 > maxV) ? 2 : 1;
- /* make sure cval is a number */
- cval = +cval;
- /*
- * cell center average trit for ambiguous cases, where
- * 0 ... below iso band
- * 1 ... within iso band
- * 2 ... above isoband
- */
- center_avg = 0;
- cell = {
- cval: cval,
- polygons: [],
- edges: {},
- x0: x0,
- x1: x1,
- x2: x2,
- x3: x3,
- x: x,
- y: y
- };
- /*
- * Compute interpolated intersections of the polygon(s)
- * with the cell borders and (i) add edges for polygon
- * trace-back, or (ii) a list of small closed polygons
- * according to look-up table
- */
- switch (cval) {
- case 85: /* 1111 */
- shapeCoordinates.square(cell, x0, x1, x2, x3, opt);
- /* fall through */
- case 0: /* 0000 */
- /* fall through */
- case 170: /* 2222 */
- break;
- /* single triangle cases */
- case 169: /* 2221 */
- shapeCoordinates.triangle_bl(cell, x0, x1, x2, x3, opt);
- break;
- case 166: /* 2212 */
- shapeCoordinates.triangle_br(cell, x0, x1, x2, x3, opt);
- break;
- case 154: /* 2122 */
- shapeCoordinates.triangle_tr(cell, x0, x1, x2, x3, opt);
- break;
- case 106: /* 1222 */
- shapeCoordinates.triangle_tl(cell, x0, x1, x2, x3, opt);
- break;
- case 1: /* 0001 */
- shapeCoordinates.triangle_bl(cell, x0, x1, x2, x3, opt);
- break;
- case 4: /* 0010 */
- shapeCoordinates.triangle_br(cell, x0, x1, x2, x3, opt);
- break;
- case 16: /* 0100 */
- shapeCoordinates.triangle_tr(cell, x0, x1, x2, x3, opt);
- break;
- case 64: /* 1000 */
- shapeCoordinates.triangle_tl(cell, x0, x1, x2, x3, opt);
- break;
- /* single trapezoid cases */
- case 168: /* 2220 */
- shapeCoordinates.tetragon_bl(cell, x0, x1, x2, x3, opt);
- break;
- case 162: /* 2202 */
- shapeCoordinates.tetragon_br(cell, x0, x1, x2, x3, opt);
- break;
- case 138: /* 2022 */
- shapeCoordinates.tetragon_tr(cell, x0, x1, x2, x3, opt);
- break;
- case 42: /* 0222 */
- shapeCoordinates.tetragon_tl(cell, x0, x1, x2, x3, opt);
- break;
- case 2: /* 0002 */
- shapeCoordinates.tetragon_bl(cell, x0, x1, x2, x3, opt);
- break;
- case 8: /* 0020 */
- shapeCoordinates.tetragon_br(cell, x0, x1, x2, x3, opt);
- break;
- case 32: /* 0200 */
- shapeCoordinates.tetragon_tr(cell, x0, x1, x2, x3, opt);
- break;
- case 128: /* 2000 */
- shapeCoordinates.tetragon_tl(cell, x0, x1, x2, x3, opt);
- break;
- /* single rectangle cases */
- case 5: /* 0011 */
- shapeCoordinates.tetragon_b(cell, x0, x1, x2, x3, opt);
- break;
- case 20: /* 0110 */
- shapeCoordinates.tetragon_r(cell, x0, x1, x2, x3, opt);
- break;
- case 80: /* 1100 */
- shapeCoordinates.tetragon_t(cell, x0, x1, x2, x3, opt);
- break;
- case 65: /* 1001 */
- shapeCoordinates.tetragon_l(cell, x0, x1, x2, x3, opt);
- break;
- case 165: /* 2211 */
- shapeCoordinates.tetragon_b(cell, x0, x1, x2, x3, opt);
- break;
- case 150: /* 2112 */
- shapeCoordinates.tetragon_r(cell, x0, x1, x2, x3, opt);
- break;
- case 90: /* 1122 */
- shapeCoordinates.tetragon_t(cell, x0, x1, x2, x3, opt);
- break;
- case 105: /* 1221 */
- shapeCoordinates.tetragon_l(cell, x0, x1, x2, x3, opt);
- break;
- case 160: /* 2200 */
- shapeCoordinates.tetragon_lr(cell, x0, x1, x2, x3, opt);
- break;
- case 130: /* 2002 */
- shapeCoordinates.tetragon_tb(cell, x0, x1, x2, x3, opt);
- break;
- case 10: /* 0022 */
- shapeCoordinates.tetragon_lr(cell, x0, x1, x2, x3, opt);
- break;
- case 40: /* 0220 */
- shapeCoordinates.tetragon_tb(cell, x0, x1, x2, x3, opt);
- break;
- /* single pentagon cases */
- case 101: /* 1211 */
- shapeCoordinates.pentagon_tr(cell, x0, x1, x2, x3, opt);
- break;
- case 149: /* 2111 */
- shapeCoordinates.pentagon_tl(cell, x0, x1, x2, x3, opt);
- break;
- case 86: /* 1112 */
- shapeCoordinates.pentagon_bl(cell, x0, x1, x2, x3, opt);
- break;
- case 89: /* 1121 */
- shapeCoordinates.pentagon_br(cell, x0, x1, x2, x3, opt);
- break;
- case 69: /* 1011 */
- shapeCoordinates.pentagon_tr(cell, x0, x1, x2, x3, opt);
- break;
- case 21: /* 0111 */
- shapeCoordinates.pentagon_tl(cell, x0, x1, x2, x3, opt);
- break;
- case 84: /* 1110 */
- shapeCoordinates.pentagon_bl(cell, x0, x1, x2, x3, opt);
- break;
- case 81: /* 1101 */
- shapeCoordinates.pentagon_br(cell, x0, x1, x2, x3, opt);
- break;
- case 96: /* 1200 */
- shapeCoordinates.pentagon_tr_rl(cell, x0, x1, x2, x3, opt);
- break;
- case 24: /* 0120 */
- shapeCoordinates.pentagon_rb_bt(cell, x0, x1, x2, x3, opt);
- break;
- case 6: /* 0012 */
- shapeCoordinates.pentagon_bl_lr(cell, x0, x1, x2, x3, opt);
- break;
- case 129: /* 2001 */
- shapeCoordinates.pentagon_lt_tb(cell, x0, x1, x2, x3, opt);
- break;
- case 74: /* 1022 */
- shapeCoordinates.pentagon_tr_rl(cell, x0, x1, x2, x3, opt);
- break;
- case 146: /* 2102 */
- shapeCoordinates.pentagon_rb_bt(cell, x0, x1, x2, x3, opt);
- break;
- case 164: /* 2210 */
- shapeCoordinates.pentagon_bl_lr(cell, x0, x1, x2, x3, opt);
- break;
- case 41: /* 0221 */
- shapeCoordinates.pentagon_lt_tb(cell, x0, x1, x2, x3, opt);
- break;
- case 66: /* 1002 */
- shapeCoordinates.pentagon_bl_tb(cell, x0, x1, x2, x3, opt);
- break;
- case 144: /* 2100 */
- shapeCoordinates.pentagon_lt_rl(cell, x0, x1, x2, x3, opt);
- break;
- case 36: /* 0210 */
- shapeCoordinates.pentagon_tr_bt(cell, x0, x1, x2, x3, opt);
- break;
- case 9: /* 0021 */
- shapeCoordinates.pentagon_rb_lr(cell, x0, x1, x2, x3, opt);
- break;
- case 104: /* 1220 */
- shapeCoordinates.pentagon_bl_tb(cell, x0, x1, x2, x3, opt);
- break;
- case 26: /* 0122 */
- shapeCoordinates.pentagon_lt_rl(cell, x0, x1, x2, x3, opt);
- break;
- case 134: /* 2012 */
- shapeCoordinates.pentagon_tr_bt(cell, x0, x1, x2, x3, opt);
- break;
- case 161: /* 2201 */
- shapeCoordinates.pentagon_rb_lr(cell, x0, x1, x2, x3, opt);
- break;
- /* single hexagon cases */
- case 37: /* 0211 */
- shapeCoordinates.hexagon_lt_tr(cell, x0, x1, x2, x3, opt);
- break;
- case 148: /* 2110 */
- shapeCoordinates.hexagon_bl_lt(cell, x0, x1, x2, x3, opt);
- break;
- case 82: /* 1102 */
- shapeCoordinates.hexagon_bl_rb(cell, x0, x1, x2, x3, opt);
- break;
- case 73: /* 1021 */
- shapeCoordinates.hexagon_tr_rb(cell, x0, x1, x2, x3, opt);
- break;
- case 133: /* 2011 */
- shapeCoordinates.hexagon_lt_tr(cell, x0, x1, x2, x3, opt);
- break;
- case 22: /* 0112 */
- shapeCoordinates.hexagon_bl_lt(cell, x0, x1, x2, x3, opt);
- break;
- case 88: /* 1120 */
- shapeCoordinates.hexagon_bl_rb(cell, x0, x1, x2, x3, opt);
- break;
- case 97: /* 1201 */
- shapeCoordinates.hexagon_tr_rb(cell, x0, x1, x2, x3, opt);
- break;
- case 145: /* 2101 */
- shapeCoordinates.hexagon_lt_rb(cell, x0, x1, x2, x3, opt);
- break;
- case 25: /* 0121 */
- shapeCoordinates.hexagon_lt_rb(cell, x0, x1, x2, x3, opt);
- break;
- case 70: /* 1012 */
- shapeCoordinates.hexagon_bl_tr(cell, x0, x1, x2, x3, opt);
- break;
- case 100: /* 1210 */
- shapeCoordinates.hexagon_bl_tr(cell, x0, x1, x2, x3, opt);
- break;
- /* 6-sided saddles */
- case 17: /* 0101 */
- center_avg = computeCenterAverage(x0, x1, x2, x3, minV, maxV);
- /* should never be center_avg === 2 */
- if (center_avg === 0) {
- shapeCoordinates.triangle_bl(cell, x0, x1, x2, x3, opt);
- shapeCoordinates.triangle_tr(cell, x0, x1, x2, x3, opt);
- } else {
- shapeCoordinates.hexagon_lt_rb(cell, x0, x1, x2, x3, opt);
- }
- break;
- case 68: /* 1010 */
- center_avg = computeCenterAverage(x0, x1, x2, x3, minV, maxV);
- /* should never be center_avg === 2 */
- if (center_avg === 0) {
- shapeCoordinates.triangle_tl(cell, x0, x1, x2, x3, opt);
- shapeCoordinates.triangle_br(cell, x0, x1, x2, x3, opt);
- } else {
- shapeCoordinates.hexagon_bl_tr(cell, x0, x1, x2, x3, opt);
- }
- break;
- case 153: /* 2121 */
- center_avg = computeCenterAverage(x0, x1, x2, x3, minV, maxV);
- /* should never be center_avg === 0 */
- if (center_avg === 2) {
- shapeCoordinates.triangle_bl(cell, x0, x1, x2, x3, opt);
- shapeCoordinates.triangle_tr(cell, x0, x1, x2, x3, opt);
- } else {
- shapeCoordinates.hexagon_lt_rb(cell, x0, x1, x2, x3, opt);
- }
- break;
- case 102: /* 1212 */
- center_avg = computeCenterAverage(x0, x1, x2, x3, minV, maxV);
- /* should never be center_avg === 0 */
- if (center_avg === 2) {
- shapeCoordinates.triangle_tl(cell, x0, x1, x2, x3, opt);
- shapeCoordinates.triangle_br(cell, x0, x1, x2, x3, opt);
- } else {
- shapeCoordinates.hexagon_bl_tr(cell, x0, x1, x2, x3, opt);
- }
- break;
- /* 7-sided saddles */
- case 152: /* 2120 */
- center_avg = computeCenterAverage(x0, x1, x2, x3, minV, maxV);
- /* should never be center_avg === 0 */
- if (center_avg === 2) {
- shapeCoordinates.triangle_tr(cell, x0, x1, x2, x3, opt);
- shapeCoordinates.tetragon_bl(cell, x0, x1, x2, x3, opt);
- } else {
- shapeCoordinates.heptagon_tr(cell, x0, x1, x2, x3, opt);
- }
- break;
- case 137: /* 2021 */
- center_avg = computeCenterAverage(x0, x1, x2, x3, minV, maxV);
- /* should never be center_avg === 0 */
- if (center_avg === 2) {
- shapeCoordinates.triangle_bl(cell, x0, x1, x2, x3, opt);
- shapeCoordinates.tetragon_tr(cell, x0, x1, x2, x3, opt);
- } else {
- shapeCoordinates.heptagon_bl(cell, x0, x1, x2, x3, opt);
- }
- break;
- case 98: /* 1202 */
- center_avg = computeCenterAverage(x0, x1, x2, x3, minV, maxV);
- /* should never be center_avg === 0 */
- if (center_avg === 2) {
- shapeCoordinates.triangle_tl(cell, x0, x1, x2, x3, opt);
- shapeCoordinates.tetragon_br(cell, x0, x1, x2, x3, opt);
- } else {
- shapeCoordinates.heptagon_tl(cell, x0, x1, x2, x3, opt);
- }
- break;
- case 38: /* 0212 */
- center_avg = computeCenterAverage(x0, x1, x2, x3, minV, maxV);
- /* should never be center_avg === 0 */
- if (center_avg === 2) {
- shapeCoordinates.triangle_br(cell, x0, x1, x2, x3, opt);
- shapeCoordinates.tetragon_tl(cell, x0, x1, x2, x3, opt);
- } else {
- shapeCoordinates.heptagon_br(cell, x0, x1, x2, x3, opt);
- }
- break;
- case 18: /* 0102 */
- center_avg = computeCenterAverage(x0, x1, x2, x3, minV, maxV);
- /* should never be center_avg === 2 */
- if (center_avg === 0) {
- shapeCoordinates.triangle_tr(cell, x0, x1, x2, x3, opt);
- shapeCoordinates.tetragon_bl(cell, x0, x1, x2, x3, opt);
- } else {
- shapeCoordinates.heptagon_tr(cell, x0, x1, x2, x3, opt);
- }
- break;
- case 33: /* 0201 */
- center_avg = computeCenterAverage(x0, x1, x2, x3, minV, maxV);
- /* should never be center_avg === 2 */
- if (center_avg === 0) {
- shapeCoordinates.triangle_bl(cell, x0, x1, x2, x3, opt);
- shapeCoordinates.tetragon_tr(cell, x0, x1, x2, x3, opt);
- } else {
- shapeCoordinates.heptagon_bl(cell, x0, x1, x2, x3, opt);
- }
- break;
- case 72: /* 1020 */
- center_avg = computeCenterAverage(x0, x1, x2, x3, minV, maxV);
- /* should never be center_avg === 2 */
- if (center_avg === 0) {
- shapeCoordinates.triangle_tl(cell, x0, x1, x2, x3, opt);
- shapeCoordinates.tetragon_br(cell, x0, x1, x2, x3, opt);
- } else {
- shapeCoordinates.heptagon_tl(cell, x0, x1, x2, x3, opt);
- }
- break;
- case 132: /* 2010 */
- center_avg = computeCenterAverage(x0, x1, x2, x3, minV, maxV);
- /* should never be center_avg === 2 */
- if (center_avg === 0) {
- shapeCoordinates.triangle_br(cell, x0, x1, x2, x3, opt);
- shapeCoordinates.tetragon_tl(cell, x0, x1, x2, x3, opt);
- } else {
- shapeCoordinates.heptagon_br(cell, x0, x1, x2, x3, opt);
- }
- break;
- /* 8-sided saddles */
- case 136: /* 2020 */
- center_avg = computeCenterAverage(x0, x1, x2, x3, minV, maxV);
- if (center_avg === 0) {
- shapeCoordinates.tetragon_tl(cell, x0, x1, x2, x3, opt);
- shapeCoordinates.tetragon_br(cell, x0, x1, x2, x3, opt);
- } else if (center_avg === 1) {
- shapeCoordinates.octagon(cell, x0, x1, x2, x3, opt);
- } else {
- shapeCoordinates.tetragon_bl(cell, x0, x1, x2, x3, opt);
- shapeCoordinates.tetragon_tr(cell, x0, x1, x2, x3, opt);
- }
- break;
- case 34: /* 0202 */
- center_avg = computeCenterAverage(x0, x1, x2, x3, minV, maxV);
- if (center_avg === 0) {
- shapeCoordinates.tetragon_bl(cell, x0, x1, x2, x3, opt);
- shapeCoordinates.tetragon_tr(cell, x0, x1, x2, x3, opt);
- } else if (center_avg === 1) {
- shapeCoordinates.octagon(cell, x0, x1, x2, x3, opt);
- } else {
- shapeCoordinates.tetragon_tl(cell, x0, x1, x2, x3, opt);
- shapeCoordinates.tetragon_br(cell, x0, x1, x2, x3, opt);
- }
- break;
- }
- return cell;
- }
- export { isoLines, isoLines as isoContours, isoBands, QuadTree, QuadTree as quadTree };
|