three-forcegraph.js 254 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249
  1. // Version 1.39.1 three-forcegraph - https://github.com/vasturiano/three-forcegraph
  2. (function (global, factory) {
  3. typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('three')) :
  4. typeof define === 'function' && define.amd ? define(['three'], factory) :
  5. (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.ThreeForceGraph = factory(global.THREE));
  6. }(this, (function (three$2) { 'use strict';
  7. function ownKeys$1(object, enumerableOnly) {
  8. var keys = Object.keys(object);
  9. if (Object.getOwnPropertySymbols) {
  10. var symbols = Object.getOwnPropertySymbols(object);
  11. if (enumerableOnly) {
  12. symbols = symbols.filter(function (sym) {
  13. return Object.getOwnPropertyDescriptor(object, sym).enumerable;
  14. });
  15. }
  16. keys.push.apply(keys, symbols);
  17. }
  18. return keys;
  19. }
  20. function _objectSpread2$1(target) {
  21. for (var i = 1; i < arguments.length; i++) {
  22. var source = arguments[i] != null ? arguments[i] : {};
  23. if (i % 2) {
  24. ownKeys$1(Object(source), true).forEach(function (key) {
  25. _defineProperty$1(target, key, source[key]);
  26. });
  27. } else if (Object.getOwnPropertyDescriptors) {
  28. Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
  29. } else {
  30. ownKeys$1(Object(source)).forEach(function (key) {
  31. Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
  32. });
  33. }
  34. }
  35. return target;
  36. }
  37. function _typeof(obj) {
  38. "@babel/helpers - typeof";
  39. if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
  40. _typeof = function (obj) {
  41. return typeof obj;
  42. };
  43. } else {
  44. _typeof = function (obj) {
  45. return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
  46. };
  47. }
  48. return _typeof(obj);
  49. }
  50. function _classCallCheck$1(instance, Constructor) {
  51. if (!(instance instanceof Constructor)) {
  52. throw new TypeError("Cannot call a class as a function");
  53. }
  54. }
  55. function _defineProperty$1(obj, key, value) {
  56. if (key in obj) {
  57. Object.defineProperty(obj, key, {
  58. value: value,
  59. enumerable: true,
  60. configurable: true,
  61. writable: true
  62. });
  63. } else {
  64. obj[key] = value;
  65. }
  66. return obj;
  67. }
  68. function _inherits(subClass, superClass) {
  69. if (typeof superClass !== "function" && superClass !== null) {
  70. throw new TypeError("Super expression must either be null or a function");
  71. }
  72. subClass.prototype = Object.create(superClass && superClass.prototype, {
  73. constructor: {
  74. value: subClass,
  75. writable: true,
  76. configurable: true
  77. }
  78. });
  79. if (superClass) _setPrototypeOf(subClass, superClass);
  80. }
  81. function _getPrototypeOf(o) {
  82. _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
  83. return o.__proto__ || Object.getPrototypeOf(o);
  84. };
  85. return _getPrototypeOf(o);
  86. }
  87. function _setPrototypeOf(o, p) {
  88. _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
  89. o.__proto__ = p;
  90. return o;
  91. };
  92. return _setPrototypeOf(o, p);
  93. }
  94. function _isNativeReflectConstruct() {
  95. if (typeof Reflect === "undefined" || !Reflect.construct) return false;
  96. if (Reflect.construct.sham) return false;
  97. if (typeof Proxy === "function") return true;
  98. try {
  99. Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
  100. return true;
  101. } catch (e) {
  102. return false;
  103. }
  104. }
  105. function _construct(Parent, args, Class) {
  106. if (_isNativeReflectConstruct()) {
  107. _construct = Reflect.construct;
  108. } else {
  109. _construct = function _construct(Parent, args, Class) {
  110. var a = [null];
  111. a.push.apply(a, args);
  112. var Constructor = Function.bind.apply(Parent, a);
  113. var instance = new Constructor();
  114. if (Class) _setPrototypeOf(instance, Class.prototype);
  115. return instance;
  116. };
  117. }
  118. return _construct.apply(null, arguments);
  119. }
  120. function _objectWithoutPropertiesLoose$2(source, excluded) {
  121. if (source == null) return {};
  122. var target = {};
  123. var sourceKeys = Object.keys(source);
  124. var key, i;
  125. for (i = 0; i < sourceKeys.length; i++) {
  126. key = sourceKeys[i];
  127. if (excluded.indexOf(key) >= 0) continue;
  128. target[key] = source[key];
  129. }
  130. return target;
  131. }
  132. function _objectWithoutProperties$2(source, excluded) {
  133. if (source == null) return {};
  134. var target = _objectWithoutPropertiesLoose$2(source, excluded);
  135. var key, i;
  136. if (Object.getOwnPropertySymbols) {
  137. var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
  138. for (i = 0; i < sourceSymbolKeys.length; i++) {
  139. key = sourceSymbolKeys[i];
  140. if (excluded.indexOf(key) >= 0) continue;
  141. if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
  142. target[key] = source[key];
  143. }
  144. }
  145. return target;
  146. }
  147. function _assertThisInitialized(self) {
  148. if (self === void 0) {
  149. throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
  150. }
  151. return self;
  152. }
  153. function _possibleConstructorReturn(self, call) {
  154. if (call && (typeof call === "object" || typeof call === "function")) {
  155. return call;
  156. }
  157. return _assertThisInitialized(self);
  158. }
  159. function _createSuper(Derived) {
  160. var hasNativeReflectConstruct = _isNativeReflectConstruct();
  161. return function _createSuperInternal() {
  162. var Super = _getPrototypeOf(Derived),
  163. result;
  164. if (hasNativeReflectConstruct) {
  165. var NewTarget = _getPrototypeOf(this).constructor;
  166. result = Reflect.construct(Super, arguments, NewTarget);
  167. } else {
  168. result = Super.apply(this, arguments);
  169. }
  170. return _possibleConstructorReturn(this, result);
  171. };
  172. }
  173. function _slicedToArray$3(arr, i) {
  174. return _arrayWithHoles$3(arr) || _iterableToArrayLimit$3(arr, i) || _unsupportedIterableToArray$3(arr, i) || _nonIterableRest$3();
  175. }
  176. function _toConsumableArray$2(arr) {
  177. return _arrayWithoutHoles$2(arr) || _iterableToArray$2(arr) || _unsupportedIterableToArray$3(arr) || _nonIterableSpread$2();
  178. }
  179. function _arrayWithoutHoles$2(arr) {
  180. if (Array.isArray(arr)) return _arrayLikeToArray$3(arr);
  181. }
  182. function _arrayWithHoles$3(arr) {
  183. if (Array.isArray(arr)) return arr;
  184. }
  185. function _iterableToArray$2(iter) {
  186. if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
  187. }
  188. function _iterableToArrayLimit$3(arr, i) {
  189. var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
  190. if (_i == null) return;
  191. var _arr = [];
  192. var _n = true;
  193. var _d = false;
  194. var _s, _e;
  195. try {
  196. for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) {
  197. _arr.push(_s.value);
  198. if (i && _arr.length === i) break;
  199. }
  200. } catch (err) {
  201. _d = true;
  202. _e = err;
  203. } finally {
  204. try {
  205. if (!_n && _i["return"] != null) _i["return"]();
  206. } finally {
  207. if (_d) throw _e;
  208. }
  209. }
  210. return _arr;
  211. }
  212. function _unsupportedIterableToArray$3(o, minLen) {
  213. if (!o) return;
  214. if (typeof o === "string") return _arrayLikeToArray$3(o, minLen);
  215. var n = Object.prototype.toString.call(o).slice(8, -1);
  216. if (n === "Object" && o.constructor) n = o.constructor.name;
  217. if (n === "Map" || n === "Set") return Array.from(o);
  218. if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$3(o, minLen);
  219. }
  220. function _arrayLikeToArray$3(arr, len) {
  221. if (len == null || len > arr.length) len = arr.length;
  222. for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
  223. return arr2;
  224. }
  225. function _nonIterableSpread$2() {
  226. throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
  227. }
  228. function _nonIterableRest$3() {
  229. throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
  230. }
  231. function d3ForceCenter(x, y, z) {
  232. var nodes, strength = 1;
  233. if (x == null) x = 0;
  234. if (y == null) y = 0;
  235. if (z == null) z = 0;
  236. function force() {
  237. var i,
  238. n = nodes.length,
  239. node,
  240. sx = 0,
  241. sy = 0,
  242. sz = 0;
  243. for (i = 0; i < n; ++i) {
  244. node = nodes[i], sx += node.x || 0, sy += node.y || 0, sz += node.z || 0;
  245. }
  246. for (sx = (sx / n - x) * strength, sy = (sy / n - y) * strength, sz = (sz / n - z) * strength, i = 0; i < n; ++i) {
  247. node = nodes[i];
  248. if (sx) { node.x -= sx; }
  249. if (sy) { node.y -= sy; }
  250. if (sz) { node.z -= sz; }
  251. }
  252. }
  253. force.initialize = function(_) {
  254. nodes = _;
  255. };
  256. force.x = function(_) {
  257. return arguments.length ? (x = +_, force) : x;
  258. };
  259. force.y = function(_) {
  260. return arguments.length ? (y = +_, force) : y;
  261. };
  262. force.z = function(_) {
  263. return arguments.length ? (z = +_, force) : z;
  264. };
  265. force.strength = function(_) {
  266. return arguments.length ? (strength = +_, force) : strength;
  267. };
  268. return force;
  269. }
  270. function tree_add$2(d) {
  271. var x = +this._x.call(null, d);
  272. return add$2(this.cover(x), x, d);
  273. }
  274. function add$2(tree, x, d) {
  275. if (isNaN(x)) return tree; // ignore invalid points
  276. var parent,
  277. node = tree._root,
  278. leaf = {data: d},
  279. x0 = tree._x0,
  280. x1 = tree._x1,
  281. xm,
  282. xp,
  283. right,
  284. i,
  285. j;
  286. // If the tree is empty, initialize the root as a leaf.
  287. if (!node) return tree._root = leaf, tree;
  288. // Find the existing leaf for the new point, or add it.
  289. while (node.length) {
  290. if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;
  291. if (parent = node, !(node = node[i = +right])) return parent[i] = leaf, tree;
  292. }
  293. // Is the new point is exactly coincident with the existing point?
  294. xp = +tree._x.call(null, node.data);
  295. if (x === xp) return leaf.next = node, parent ? parent[i] = leaf : tree._root = leaf, tree;
  296. // Otherwise, split the leaf node until the old and new point are separated.
  297. do {
  298. parent = parent ? parent[i] = new Array(2) : tree._root = new Array(2);
  299. if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;
  300. } while ((i = +right) === (j = +(xp >= xm)));
  301. return parent[j] = node, parent[i] = leaf, tree;
  302. }
  303. function addAll$2(data) {
  304. var i, n = data.length,
  305. x,
  306. xz = new Array(n),
  307. x0 = Infinity,
  308. x1 = -Infinity;
  309. // Compute the points and their extent.
  310. for (i = 0; i < n; ++i) {
  311. if (isNaN(x = +this._x.call(null, data[i]))) continue;
  312. xz[i] = x;
  313. if (x < x0) x0 = x;
  314. if (x > x1) x1 = x;
  315. }
  316. // If there were no (valid) points, abort.
  317. if (x0 > x1) return this;
  318. // Expand the tree to cover the new points.
  319. this.cover(x0).cover(x1);
  320. // Add the new points.
  321. for (i = 0; i < n; ++i) {
  322. add$2(this, xz[i], data[i]);
  323. }
  324. return this;
  325. }
  326. function tree_cover$2(x) {
  327. if (isNaN(x = +x)) return this; // ignore invalid points
  328. var x0 = this._x0,
  329. x1 = this._x1;
  330. // If the binarytree has no extent, initialize them.
  331. // Integer extent are necessary so that if we later double the extent,
  332. // the existing half boundaries don’t change due to floating point error!
  333. if (isNaN(x0)) {
  334. x1 = (x0 = Math.floor(x)) + 1;
  335. }
  336. // Otherwise, double repeatedly to cover.
  337. else {
  338. var z = x1 - x0 || 1,
  339. node = this._root,
  340. parent,
  341. i;
  342. while (x0 > x || x >= x1) {
  343. i = +(x < x0);
  344. parent = new Array(2), parent[i] = node, node = parent, z *= 2;
  345. switch (i) {
  346. case 0: x1 = x0 + z; break;
  347. case 1: x0 = x1 - z; break;
  348. }
  349. }
  350. if (this._root && this._root.length) this._root = node;
  351. }
  352. this._x0 = x0;
  353. this._x1 = x1;
  354. return this;
  355. }
  356. function tree_data$2() {
  357. var data = [];
  358. this.visit(function(node) {
  359. if (!node.length) do data.push(node.data); while (node = node.next)
  360. });
  361. return data;
  362. }
  363. function tree_extent$2(_) {
  364. return arguments.length
  365. ? this.cover(+_[0][0]).cover(+_[1][0])
  366. : isNaN(this._x0) ? undefined : [[this._x0], [this._x1]];
  367. }
  368. function Half(node, x0, x1) {
  369. this.node = node;
  370. this.x0 = x0;
  371. this.x1 = x1;
  372. }
  373. function tree_find$2(x, radius) {
  374. var data,
  375. x0 = this._x0,
  376. x1,
  377. x2,
  378. x3 = this._x1,
  379. halves = [],
  380. node = this._root,
  381. q,
  382. i;
  383. if (node) halves.push(new Half(node, x0, x3));
  384. if (radius == null) radius = Infinity;
  385. else {
  386. x0 = x - radius;
  387. x3 = x + radius;
  388. }
  389. while (q = halves.pop()) {
  390. // Stop searching if this half can’t contain a closer node.
  391. if (!(node = q.node)
  392. || (x1 = q.x0) > x3
  393. || (x2 = q.x1) < x0) continue;
  394. // Bisect the current half.
  395. if (node.length) {
  396. var xm = (x1 + x2) / 2;
  397. halves.push(
  398. new Half(node[1], xm, x2),
  399. new Half(node[0], x1, xm)
  400. );
  401. // Visit the closest half first.
  402. if (i = +(x >= xm)) {
  403. q = halves[halves.length - 1];
  404. halves[halves.length - 1] = halves[halves.length - 1 - i];
  405. halves[halves.length - 1 - i] = q;
  406. }
  407. }
  408. // Visit this point. (Visiting coincident points isn’t necessary!)
  409. else {
  410. var d = Math.abs(x - +this._x.call(null, node.data));
  411. if (d < radius) {
  412. radius = d;
  413. x0 = x - d;
  414. x3 = x + d;
  415. data = node.data;
  416. }
  417. }
  418. }
  419. return data;
  420. }
  421. function tree_remove$2(d) {
  422. if (isNaN(x = +this._x.call(null, d))) return this; // ignore invalid points
  423. var parent,
  424. node = this._root,
  425. retainer,
  426. previous,
  427. next,
  428. x0 = this._x0,
  429. x1 = this._x1,
  430. x,
  431. xm,
  432. right,
  433. i,
  434. j;
  435. // If the tree is empty, initialize the root as a leaf.
  436. if (!node) return this;
  437. // Find the leaf node for the point.
  438. // While descending, also retain the deepest parent with a non-removed sibling.
  439. if (node.length) while (true) {
  440. if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;
  441. if (!(parent = node, node = node[i = +right])) return this;
  442. if (!node.length) break;
  443. if (parent[(i + 1) & 1]) retainer = parent, j = i;
  444. }
  445. // Find the point to remove.
  446. while (node.data !== d) if (!(previous = node, node = node.next)) return this;
  447. if (next = node.next) delete node.next;
  448. // If there are multiple coincident points, remove just the point.
  449. if (previous) return (next ? previous.next = next : delete previous.next), this;
  450. // If this is the root point, remove it.
  451. if (!parent) return this._root = next, this;
  452. // Remove this leaf.
  453. next ? parent[i] = next : delete parent[i];
  454. // If the parent now contains exactly one leaf, collapse superfluous parents.
  455. if ((node = parent[0] || parent[1])
  456. && node === (parent[1] || parent[0])
  457. && !node.length) {
  458. if (retainer) retainer[j] = node;
  459. else this._root = node;
  460. }
  461. return this;
  462. }
  463. function removeAll$2(data) {
  464. for (var i = 0, n = data.length; i < n; ++i) this.remove(data[i]);
  465. return this;
  466. }
  467. function tree_root$2() {
  468. return this._root;
  469. }
  470. function tree_size$2() {
  471. var size = 0;
  472. this.visit(function(node) {
  473. if (!node.length) do ++size; while (node = node.next)
  474. });
  475. return size;
  476. }
  477. function tree_visit$2(callback) {
  478. var halves = [], q, node = this._root, child, x0, x1;
  479. if (node) halves.push(new Half(node, this._x0, this._x1));
  480. while (q = halves.pop()) {
  481. if (!callback(node = q.node, x0 = q.x0, x1 = q.x1) && node.length) {
  482. var xm = (x0 + x1) / 2;
  483. if (child = node[1]) halves.push(new Half(child, xm, x1));
  484. if (child = node[0]) halves.push(new Half(child, x0, xm));
  485. }
  486. }
  487. return this;
  488. }
  489. function tree_visitAfter$2(callback) {
  490. var halves = [], next = [], q;
  491. if (this._root) halves.push(new Half(this._root, this._x0, this._x1));
  492. while (q = halves.pop()) {
  493. var node = q.node;
  494. if (node.length) {
  495. var child, x0 = q.x0, x1 = q.x1, xm = (x0 + x1) / 2;
  496. if (child = node[0]) halves.push(new Half(child, x0, xm));
  497. if (child = node[1]) halves.push(new Half(child, xm, x1));
  498. }
  499. next.push(q);
  500. }
  501. while (q = next.pop()) {
  502. callback(q.node, q.x0, q.x1);
  503. }
  504. return this;
  505. }
  506. function defaultX$2(d) {
  507. return d[0];
  508. }
  509. function tree_x$2(_) {
  510. return arguments.length ? (this._x = _, this) : this._x;
  511. }
  512. function binarytree(nodes, x) {
  513. var tree = new Binarytree(x == null ? defaultX$2 : x, NaN, NaN);
  514. return nodes == null ? tree : tree.addAll(nodes);
  515. }
  516. function Binarytree(x, x0, x1) {
  517. this._x = x;
  518. this._x0 = x0;
  519. this._x1 = x1;
  520. this._root = undefined;
  521. }
  522. function leaf_copy$2(leaf) {
  523. var copy = {data: leaf.data}, next = copy;
  524. while (leaf = leaf.next) next = next.next = {data: leaf.data};
  525. return copy;
  526. }
  527. var treeProto$2 = binarytree.prototype = Binarytree.prototype;
  528. treeProto$2.copy = function() {
  529. var copy = new Binarytree(this._x, this._x0, this._x1),
  530. node = this._root,
  531. nodes,
  532. child;
  533. if (!node) return copy;
  534. if (!node.length) return copy._root = leaf_copy$2(node), copy;
  535. nodes = [{source: node, target: copy._root = new Array(2)}];
  536. while (node = nodes.pop()) {
  537. for (var i = 0; i < 2; ++i) {
  538. if (child = node.source[i]) {
  539. if (child.length) nodes.push({source: child, target: node.target[i] = new Array(2)});
  540. else node.target[i] = leaf_copy$2(child);
  541. }
  542. }
  543. }
  544. return copy;
  545. };
  546. treeProto$2.add = tree_add$2;
  547. treeProto$2.addAll = addAll$2;
  548. treeProto$2.cover = tree_cover$2;
  549. treeProto$2.data = tree_data$2;
  550. treeProto$2.extent = tree_extent$2;
  551. treeProto$2.find = tree_find$2;
  552. treeProto$2.remove = tree_remove$2;
  553. treeProto$2.removeAll = removeAll$2;
  554. treeProto$2.root = tree_root$2;
  555. treeProto$2.size = tree_size$2;
  556. treeProto$2.visit = tree_visit$2;
  557. treeProto$2.visitAfter = tree_visitAfter$2;
  558. treeProto$2.x = tree_x$2;
  559. function tree_add$1(d) {
  560. const x = +this._x.call(null, d),
  561. y = +this._y.call(null, d);
  562. return add$1(this.cover(x, y), x, y, d);
  563. }
  564. function add$1(tree, x, y, d) {
  565. if (isNaN(x) || isNaN(y)) return tree; // ignore invalid points
  566. var parent,
  567. node = tree._root,
  568. leaf = {data: d},
  569. x0 = tree._x0,
  570. y0 = tree._y0,
  571. x1 = tree._x1,
  572. y1 = tree._y1,
  573. xm,
  574. ym,
  575. xp,
  576. yp,
  577. right,
  578. bottom,
  579. i,
  580. j;
  581. // If the tree is empty, initialize the root as a leaf.
  582. if (!node) return tree._root = leaf, tree;
  583. // Find the existing leaf for the new point, or add it.
  584. while (node.length) {
  585. if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;
  586. if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;
  587. if (parent = node, !(node = node[i = bottom << 1 | right])) return parent[i] = leaf, tree;
  588. }
  589. // Is the new point is exactly coincident with the existing point?
  590. xp = +tree._x.call(null, node.data);
  591. yp = +tree._y.call(null, node.data);
  592. if (x === xp && y === yp) return leaf.next = node, parent ? parent[i] = leaf : tree._root = leaf, tree;
  593. // Otherwise, split the leaf node until the old and new point are separated.
  594. do {
  595. parent = parent ? parent[i] = new Array(4) : tree._root = new Array(4);
  596. if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;
  597. if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;
  598. } while ((i = bottom << 1 | right) === (j = (yp >= ym) << 1 | (xp >= xm)));
  599. return parent[j] = node, parent[i] = leaf, tree;
  600. }
  601. function addAll$1(data) {
  602. var d, i, n = data.length,
  603. x,
  604. y,
  605. xz = new Array(n),
  606. yz = new Array(n),
  607. x0 = Infinity,
  608. y0 = Infinity,
  609. x1 = -Infinity,
  610. y1 = -Infinity;
  611. // Compute the points and their extent.
  612. for (i = 0; i < n; ++i) {
  613. if (isNaN(x = +this._x.call(null, d = data[i])) || isNaN(y = +this._y.call(null, d))) continue;
  614. xz[i] = x;
  615. yz[i] = y;
  616. if (x < x0) x0 = x;
  617. if (x > x1) x1 = x;
  618. if (y < y0) y0 = y;
  619. if (y > y1) y1 = y;
  620. }
  621. // If there were no (valid) points, abort.
  622. if (x0 > x1 || y0 > y1) return this;
  623. // Expand the tree to cover the new points.
  624. this.cover(x0, y0).cover(x1, y1);
  625. // Add the new points.
  626. for (i = 0; i < n; ++i) {
  627. add$1(this, xz[i], yz[i], data[i]);
  628. }
  629. return this;
  630. }
  631. function tree_cover$1(x, y) {
  632. if (isNaN(x = +x) || isNaN(y = +y)) return this; // ignore invalid points
  633. var x0 = this._x0,
  634. y0 = this._y0,
  635. x1 = this._x1,
  636. y1 = this._y1;
  637. // If the quadtree has no extent, initialize them.
  638. // Integer extent are necessary so that if we later double the extent,
  639. // the existing quadrant boundaries don’t change due to floating point error!
  640. if (isNaN(x0)) {
  641. x1 = (x0 = Math.floor(x)) + 1;
  642. y1 = (y0 = Math.floor(y)) + 1;
  643. }
  644. // Otherwise, double repeatedly to cover.
  645. else {
  646. var z = x1 - x0 || 1,
  647. node = this._root,
  648. parent,
  649. i;
  650. while (x0 > x || x >= x1 || y0 > y || y >= y1) {
  651. i = (y < y0) << 1 | (x < x0);
  652. parent = new Array(4), parent[i] = node, node = parent, z *= 2;
  653. switch (i) {
  654. case 0: x1 = x0 + z, y1 = y0 + z; break;
  655. case 1: x0 = x1 - z, y1 = y0 + z; break;
  656. case 2: x1 = x0 + z, y0 = y1 - z; break;
  657. case 3: x0 = x1 - z, y0 = y1 - z; break;
  658. }
  659. }
  660. if (this._root && this._root.length) this._root = node;
  661. }
  662. this._x0 = x0;
  663. this._y0 = y0;
  664. this._x1 = x1;
  665. this._y1 = y1;
  666. return this;
  667. }
  668. function tree_data$1() {
  669. var data = [];
  670. this.visit(function(node) {
  671. if (!node.length) do data.push(node.data); while (node = node.next)
  672. });
  673. return data;
  674. }
  675. function tree_extent$1(_) {
  676. return arguments.length
  677. ? this.cover(+_[0][0], +_[0][1]).cover(+_[1][0], +_[1][1])
  678. : isNaN(this._x0) ? undefined : [[this._x0, this._y0], [this._x1, this._y1]];
  679. }
  680. function Quad(node, x0, y0, x1, y1) {
  681. this.node = node;
  682. this.x0 = x0;
  683. this.y0 = y0;
  684. this.x1 = x1;
  685. this.y1 = y1;
  686. }
  687. function tree_find$1(x, y, radius) {
  688. var data,
  689. x0 = this._x0,
  690. y0 = this._y0,
  691. x1,
  692. y1,
  693. x2,
  694. y2,
  695. x3 = this._x1,
  696. y3 = this._y1,
  697. quads = [],
  698. node = this._root,
  699. q,
  700. i;
  701. if (node) quads.push(new Quad(node, x0, y0, x3, y3));
  702. if (radius == null) radius = Infinity;
  703. else {
  704. x0 = x - radius, y0 = y - radius;
  705. x3 = x + radius, y3 = y + radius;
  706. radius *= radius;
  707. }
  708. while (q = quads.pop()) {
  709. // Stop searching if this quadrant can’t contain a closer node.
  710. if (!(node = q.node)
  711. || (x1 = q.x0) > x3
  712. || (y1 = q.y0) > y3
  713. || (x2 = q.x1) < x0
  714. || (y2 = q.y1) < y0) continue;
  715. // Bisect the current quadrant.
  716. if (node.length) {
  717. var xm = (x1 + x2) / 2,
  718. ym = (y1 + y2) / 2;
  719. quads.push(
  720. new Quad(node[3], xm, ym, x2, y2),
  721. new Quad(node[2], x1, ym, xm, y2),
  722. new Quad(node[1], xm, y1, x2, ym),
  723. new Quad(node[0], x1, y1, xm, ym)
  724. );
  725. // Visit the closest quadrant first.
  726. if (i = (y >= ym) << 1 | (x >= xm)) {
  727. q = quads[quads.length - 1];
  728. quads[quads.length - 1] = quads[quads.length - 1 - i];
  729. quads[quads.length - 1 - i] = q;
  730. }
  731. }
  732. // Visit this point. (Visiting coincident points isn’t necessary!)
  733. else {
  734. var dx = x - +this._x.call(null, node.data),
  735. dy = y - +this._y.call(null, node.data),
  736. d2 = dx * dx + dy * dy;
  737. if (d2 < radius) {
  738. var d = Math.sqrt(radius = d2);
  739. x0 = x - d, y0 = y - d;
  740. x3 = x + d, y3 = y + d;
  741. data = node.data;
  742. }
  743. }
  744. }
  745. return data;
  746. }
  747. function tree_remove$1(d) {
  748. if (isNaN(x = +this._x.call(null, d)) || isNaN(y = +this._y.call(null, d))) return this; // ignore invalid points
  749. var parent,
  750. node = this._root,
  751. retainer,
  752. previous,
  753. next,
  754. x0 = this._x0,
  755. y0 = this._y0,
  756. x1 = this._x1,
  757. y1 = this._y1,
  758. x,
  759. y,
  760. xm,
  761. ym,
  762. right,
  763. bottom,
  764. i,
  765. j;
  766. // If the tree is empty, initialize the root as a leaf.
  767. if (!node) return this;
  768. // Find the leaf node for the point.
  769. // While descending, also retain the deepest parent with a non-removed sibling.
  770. if (node.length) while (true) {
  771. if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;
  772. if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;
  773. if (!(parent = node, node = node[i = bottom << 1 | right])) return this;
  774. if (!node.length) break;
  775. if (parent[(i + 1) & 3] || parent[(i + 2) & 3] || parent[(i + 3) & 3]) retainer = parent, j = i;
  776. }
  777. // Find the point to remove.
  778. while (node.data !== d) if (!(previous = node, node = node.next)) return this;
  779. if (next = node.next) delete node.next;
  780. // If there are multiple coincident points, remove just the point.
  781. if (previous) return (next ? previous.next = next : delete previous.next), this;
  782. // If this is the root point, remove it.
  783. if (!parent) return this._root = next, this;
  784. // Remove this leaf.
  785. next ? parent[i] = next : delete parent[i];
  786. // If the parent now contains exactly one leaf, collapse superfluous parents.
  787. if ((node = parent[0] || parent[1] || parent[2] || parent[3])
  788. && node === (parent[3] || parent[2] || parent[1] || parent[0])
  789. && !node.length) {
  790. if (retainer) retainer[j] = node;
  791. else this._root = node;
  792. }
  793. return this;
  794. }
  795. function removeAll$1(data) {
  796. for (var i = 0, n = data.length; i < n; ++i) this.remove(data[i]);
  797. return this;
  798. }
  799. function tree_root$1() {
  800. return this._root;
  801. }
  802. function tree_size$1() {
  803. var size = 0;
  804. this.visit(function(node) {
  805. if (!node.length) do ++size; while (node = node.next)
  806. });
  807. return size;
  808. }
  809. function tree_visit$1(callback) {
  810. var quads = [], q, node = this._root, child, x0, y0, x1, y1;
  811. if (node) quads.push(new Quad(node, this._x0, this._y0, this._x1, this._y1));
  812. while (q = quads.pop()) {
  813. if (!callback(node = q.node, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1) && node.length) {
  814. var xm = (x0 + x1) / 2, ym = (y0 + y1) / 2;
  815. if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1));
  816. if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1));
  817. if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym));
  818. if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym));
  819. }
  820. }
  821. return this;
  822. }
  823. function tree_visitAfter$1(callback) {
  824. var quads = [], next = [], q;
  825. if (this._root) quads.push(new Quad(this._root, this._x0, this._y0, this._x1, this._y1));
  826. while (q = quads.pop()) {
  827. var node = q.node;
  828. if (node.length) {
  829. var child, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1, xm = (x0 + x1) / 2, ym = (y0 + y1) / 2;
  830. if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym));
  831. if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym));
  832. if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1));
  833. if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1));
  834. }
  835. next.push(q);
  836. }
  837. while (q = next.pop()) {
  838. callback(q.node, q.x0, q.y0, q.x1, q.y1);
  839. }
  840. return this;
  841. }
  842. function defaultX$1(d) {
  843. return d[0];
  844. }
  845. function tree_x$1(_) {
  846. return arguments.length ? (this._x = _, this) : this._x;
  847. }
  848. function defaultY$1(d) {
  849. return d[1];
  850. }
  851. function tree_y$1(_) {
  852. return arguments.length ? (this._y = _, this) : this._y;
  853. }
  854. function quadtree(nodes, x, y) {
  855. var tree = new Quadtree(x == null ? defaultX$1 : x, y == null ? defaultY$1 : y, NaN, NaN, NaN, NaN);
  856. return nodes == null ? tree : tree.addAll(nodes);
  857. }
  858. function Quadtree(x, y, x0, y0, x1, y1) {
  859. this._x = x;
  860. this._y = y;
  861. this._x0 = x0;
  862. this._y0 = y0;
  863. this._x1 = x1;
  864. this._y1 = y1;
  865. this._root = undefined;
  866. }
  867. function leaf_copy$1(leaf) {
  868. var copy = {data: leaf.data}, next = copy;
  869. while (leaf = leaf.next) next = next.next = {data: leaf.data};
  870. return copy;
  871. }
  872. var treeProto$1 = quadtree.prototype = Quadtree.prototype;
  873. treeProto$1.copy = function() {
  874. var copy = new Quadtree(this._x, this._y, this._x0, this._y0, this._x1, this._y1),
  875. node = this._root,
  876. nodes,
  877. child;
  878. if (!node) return copy;
  879. if (!node.length) return copy._root = leaf_copy$1(node), copy;
  880. nodes = [{source: node, target: copy._root = new Array(4)}];
  881. while (node = nodes.pop()) {
  882. for (var i = 0; i < 4; ++i) {
  883. if (child = node.source[i]) {
  884. if (child.length) nodes.push({source: child, target: node.target[i] = new Array(4)});
  885. else node.target[i] = leaf_copy$1(child);
  886. }
  887. }
  888. }
  889. return copy;
  890. };
  891. treeProto$1.add = tree_add$1;
  892. treeProto$1.addAll = addAll$1;
  893. treeProto$1.cover = tree_cover$1;
  894. treeProto$1.data = tree_data$1;
  895. treeProto$1.extent = tree_extent$1;
  896. treeProto$1.find = tree_find$1;
  897. treeProto$1.remove = tree_remove$1;
  898. treeProto$1.removeAll = removeAll$1;
  899. treeProto$1.root = tree_root$1;
  900. treeProto$1.size = tree_size$1;
  901. treeProto$1.visit = tree_visit$1;
  902. treeProto$1.visitAfter = tree_visitAfter$1;
  903. treeProto$1.x = tree_x$1;
  904. treeProto$1.y = tree_y$1;
  905. function tree_add(d) {
  906. var x = +this._x.call(null, d),
  907. y = +this._y.call(null, d),
  908. z = +this._z.call(null, d);
  909. return add(this.cover(x, y, z), x, y, z, d);
  910. }
  911. function add(tree, x, y, z, d) {
  912. if (isNaN(x) || isNaN(y) || isNaN(z)) return tree; // ignore invalid points
  913. var parent,
  914. node = tree._root,
  915. leaf = {data: d},
  916. x0 = tree._x0,
  917. y0 = tree._y0,
  918. z0 = tree._z0,
  919. x1 = tree._x1,
  920. y1 = tree._y1,
  921. z1 = tree._z1,
  922. xm,
  923. ym,
  924. zm,
  925. xp,
  926. yp,
  927. zp,
  928. right,
  929. bottom,
  930. deep,
  931. i,
  932. j;
  933. // If the tree is empty, initialize the root as a leaf.
  934. if (!node) return tree._root = leaf, tree;
  935. // Find the existing leaf for the new point, or add it.
  936. while (node.length) {
  937. if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;
  938. if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;
  939. if (deep = z >= (zm = (z0 + z1) / 2)) z0 = zm; else z1 = zm;
  940. if (parent = node, !(node = node[i = deep << 2 | bottom << 1 | right])) return parent[i] = leaf, tree;
  941. }
  942. // Is the new point is exactly coincident with the existing point?
  943. xp = +tree._x.call(null, node.data);
  944. yp = +tree._y.call(null, node.data);
  945. zp = +tree._z.call(null, node.data);
  946. if (x === xp && y === yp && z === zp) return leaf.next = node, parent ? parent[i] = leaf : tree._root = leaf, tree;
  947. // Otherwise, split the leaf node until the old and new point are separated.
  948. do {
  949. parent = parent ? parent[i] = new Array(8) : tree._root = new Array(8);
  950. if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;
  951. if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;
  952. if (deep = z >= (zm = (z0 + z1) / 2)) z0 = zm; else z1 = zm;
  953. } while ((i = deep << 2 | bottom << 1 | right) === (j = (zp >= zm) << 2 | (yp >= ym) << 1 | (xp >= xm)));
  954. return parent[j] = node, parent[i] = leaf, tree;
  955. }
  956. function addAll(data) {
  957. var d, i, n = data.length,
  958. x,
  959. y,
  960. z,
  961. xz = new Array(n),
  962. yz = new Array(n),
  963. zz = new Array(n),
  964. x0 = Infinity,
  965. y0 = Infinity,
  966. z0 = Infinity,
  967. x1 = -Infinity,
  968. y1 = -Infinity,
  969. z1 = -Infinity;
  970. // Compute the points and their extent.
  971. for (i = 0; i < n; ++i) {
  972. if (isNaN(x = +this._x.call(null, d = data[i])) || isNaN(y = +this._y.call(null, d)) || isNaN(z = +this._z.call(null, d))) continue;
  973. xz[i] = x;
  974. yz[i] = y;
  975. zz[i] = z;
  976. if (x < x0) x0 = x;
  977. if (x > x1) x1 = x;
  978. if (y < y0) y0 = y;
  979. if (y > y1) y1 = y;
  980. if (z < z0) z0 = z;
  981. if (z > z1) z1 = z;
  982. }
  983. // If there were no (valid) points, abort.
  984. if (x0 > x1 || y0 > y1 || z0 > z1) return this;
  985. // Expand the tree to cover the new points.
  986. this.cover(x0, y0, z0).cover(x1, y1, z1);
  987. // Add the new points.
  988. for (i = 0; i < n; ++i) {
  989. add(this, xz[i], yz[i], zz[i], data[i]);
  990. }
  991. return this;
  992. }
  993. function tree_cover(x, y, z) {
  994. if (isNaN(x = +x) || isNaN(y = +y) || isNaN(z = +z)) return this; // ignore invalid points
  995. var x0 = this._x0,
  996. y0 = this._y0,
  997. z0 = this._z0,
  998. x1 = this._x1,
  999. y1 = this._y1,
  1000. z1 = this._z1;
  1001. // If the octree has no extent, initialize them.
  1002. // Integer extent are necessary so that if we later double the extent,
  1003. // the existing octant boundaries don’t change due to floating point error!
  1004. if (isNaN(x0)) {
  1005. x1 = (x0 = Math.floor(x)) + 1;
  1006. y1 = (y0 = Math.floor(y)) + 1;
  1007. z1 = (z0 = Math.floor(z)) + 1;
  1008. }
  1009. // Otherwise, double repeatedly to cover.
  1010. else {
  1011. var t = x1 - x0 || 1,
  1012. node = this._root,
  1013. parent,
  1014. i;
  1015. while (x0 > x || x >= x1 || y0 > y || y >= y1 || z0 > z || z >= z1) {
  1016. i = (z < z0) << 2 | (y < y0) << 1 | (x < x0);
  1017. parent = new Array(8), parent[i] = node, node = parent, t *= 2;
  1018. switch (i) {
  1019. case 0: x1 = x0 + t, y1 = y0 + t, z1 = z0 + t; break;
  1020. case 1: x0 = x1 - t, y1 = y0 + t, z1 = z0 + t; break;
  1021. case 2: x1 = x0 + t, y0 = y1 - t, z1 = z0 + t; break;
  1022. case 3: x0 = x1 - t, y0 = y1 - t, z1 = z0 + t; break;
  1023. case 4: x1 = x0 + t, y1 = y0 + t, z0 = z1 - t; break;
  1024. case 5: x0 = x1 - t, y1 = y0 + t, z0 = z1 - t; break;
  1025. case 6: x1 = x0 + t, y0 = y1 - t, z0 = z1 - t; break;
  1026. case 7: x0 = x1 - t, y0 = y1 - t, z0 = z1 - t; break;
  1027. }
  1028. }
  1029. if (this._root && this._root.length) this._root = node;
  1030. }
  1031. this._x0 = x0;
  1032. this._y0 = y0;
  1033. this._z0 = z0;
  1034. this._x1 = x1;
  1035. this._y1 = y1;
  1036. this._z1 = z1;
  1037. return this;
  1038. }
  1039. function tree_data() {
  1040. var data = [];
  1041. this.visit(function(node) {
  1042. if (!node.length) do data.push(node.data); while (node = node.next)
  1043. });
  1044. return data;
  1045. }
  1046. function tree_extent(_) {
  1047. return arguments.length
  1048. ? this.cover(+_[0][0], +_[0][1], +_[0][2]).cover(+_[1][0], +_[1][1], +_[1][2])
  1049. : isNaN(this._x0) ? undefined : [[this._x0, this._y0, this._z0], [this._x1, this._y1, this._z1]];
  1050. }
  1051. function Octant(node, x0, y0, z0, x1, y1, z1) {
  1052. this.node = node;
  1053. this.x0 = x0;
  1054. this.y0 = y0;
  1055. this.z0 = z0;
  1056. this.x1 = x1;
  1057. this.y1 = y1;
  1058. this.z1 = z1;
  1059. }
  1060. function tree_find(x, y, z, radius) {
  1061. var data,
  1062. x0 = this._x0,
  1063. y0 = this._y0,
  1064. z0 = this._z0,
  1065. x1,
  1066. y1,
  1067. z1,
  1068. x2,
  1069. y2,
  1070. z2,
  1071. x3 = this._x1,
  1072. y3 = this._y1,
  1073. z3 = this._z1,
  1074. octs = [],
  1075. node = this._root,
  1076. q,
  1077. i;
  1078. if (node) octs.push(new Octant(node, x0, y0, z0, x3, y3, z3));
  1079. if (radius == null) radius = Infinity;
  1080. else {
  1081. x0 = x - radius, y0 = y - radius, z0 = z - radius;
  1082. x3 = x + radius, y3 = y + radius, z3 = z + radius;
  1083. radius *= radius;
  1084. }
  1085. while (q = octs.pop()) {
  1086. // Stop searching if this octant can’t contain a closer node.
  1087. if (!(node = q.node)
  1088. || (x1 = q.x0) > x3
  1089. || (y1 = q.y0) > y3
  1090. || (z1 = q.z0) > z3
  1091. || (x2 = q.x1) < x0
  1092. || (y2 = q.y1) < y0
  1093. || (z2 = q.z1) < z0) continue;
  1094. // Bisect the current octant.
  1095. if (node.length) {
  1096. var xm = (x1 + x2) / 2,
  1097. ym = (y1 + y2) / 2,
  1098. zm = (z1 + z2) / 2;
  1099. octs.push(
  1100. new Octant(node[7], xm, ym, zm, x2, y2, z2),
  1101. new Octant(node[6], x1, ym, zm, xm, y2, z2),
  1102. new Octant(node[5], xm, y1, zm, x2, ym, z2),
  1103. new Octant(node[4], x1, y1, zm, xm, ym, z2),
  1104. new Octant(node[3], xm, ym, z1, x2, y2, zm),
  1105. new Octant(node[2], x1, ym, z1, xm, y2, zm),
  1106. new Octant(node[1], xm, y1, z1, x2, ym, zm),
  1107. new Octant(node[0], x1, y1, z1, xm, ym, zm)
  1108. );
  1109. // Visit the closest octant first.
  1110. if (i = (z >= zm) << 2 | (y >= ym) << 1 | (x >= xm)) {
  1111. q = octs[octs.length - 1];
  1112. octs[octs.length - 1] = octs[octs.length - 1 - i];
  1113. octs[octs.length - 1 - i] = q;
  1114. }
  1115. }
  1116. // Visit this point. (Visiting coincident points isn’t necessary!)
  1117. else {
  1118. var dx = x - +this._x.call(null, node.data),
  1119. dy = y - +this._y.call(null, node.data),
  1120. dz = z - +this._z.call(null, node.data),
  1121. d2 = dx * dx + dy * dy + dz * dz;
  1122. if (d2 < radius) {
  1123. var d = Math.sqrt(radius = d2);
  1124. x0 = x - d, y0 = y - d, z0 = z - d;
  1125. x3 = x + d, y3 = y + d, z3 = z + d;
  1126. data = node.data;
  1127. }
  1128. }
  1129. }
  1130. return data;
  1131. }
  1132. function tree_remove(d) {
  1133. if (isNaN(x = +this._x.call(null, d)) || isNaN(y = +this._y.call(null, d)) || isNaN(z = +this._z.call(null, d))) return this; // ignore invalid points
  1134. var parent,
  1135. node = this._root,
  1136. retainer,
  1137. previous,
  1138. next,
  1139. x0 = this._x0,
  1140. y0 = this._y0,
  1141. z0 = this._z0,
  1142. x1 = this._x1,
  1143. y1 = this._y1,
  1144. z1 = this._z1,
  1145. x,
  1146. y,
  1147. z,
  1148. xm,
  1149. ym,
  1150. zm,
  1151. right,
  1152. bottom,
  1153. deep,
  1154. i,
  1155. j;
  1156. // If the tree is empty, initialize the root as a leaf.
  1157. if (!node) return this;
  1158. // Find the leaf node for the point.
  1159. // While descending, also retain the deepest parent with a non-removed sibling.
  1160. if (node.length) while (true) {
  1161. if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;
  1162. if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;
  1163. if (deep = z >= (zm = (z0 + z1) / 2)) z0 = zm; else z1 = zm;
  1164. if (!(parent = node, node = node[i = deep << 2 | bottom << 1 | right])) return this;
  1165. if (!node.length) break;
  1166. if (parent[(i + 1) & 7] || parent[(i + 2) & 7] || parent[(i + 3) & 7] || parent[(i + 4) & 7] || parent[(i + 5) & 7] || parent[(i + 6) & 7] || parent[(i + 7) & 7]) retainer = parent, j = i;
  1167. }
  1168. // Find the point to remove.
  1169. while (node.data !== d) if (!(previous = node, node = node.next)) return this;
  1170. if (next = node.next) delete node.next;
  1171. // If there are multiple coincident points, remove just the point.
  1172. if (previous) return (next ? previous.next = next : delete previous.next), this;
  1173. // If this is the root point, remove it.
  1174. if (!parent) return this._root = next, this;
  1175. // Remove this leaf.
  1176. next ? parent[i] = next : delete parent[i];
  1177. // If the parent now contains exactly one leaf, collapse superfluous parents.
  1178. if ((node = parent[0] || parent[1] || parent[2] || parent[3] || parent[4] || parent[5] || parent[6] || parent[7])
  1179. && node === (parent[7] || parent[6] || parent[5] || parent[4] || parent[3] || parent[2] || parent[1] || parent[0])
  1180. && !node.length) {
  1181. if (retainer) retainer[j] = node;
  1182. else this._root = node;
  1183. }
  1184. return this;
  1185. }
  1186. function removeAll(data) {
  1187. for (var i = 0, n = data.length; i < n; ++i) this.remove(data[i]);
  1188. return this;
  1189. }
  1190. function tree_root() {
  1191. return this._root;
  1192. }
  1193. function tree_size() {
  1194. var size = 0;
  1195. this.visit(function(node) {
  1196. if (!node.length) do ++size; while (node = node.next)
  1197. });
  1198. return size;
  1199. }
  1200. function tree_visit(callback) {
  1201. var octs = [], q, node = this._root, child, x0, y0, z0, x1, y1, z1;
  1202. if (node) octs.push(new Octant(node, this._x0, this._y0, this._z0, this._x1, this._y1, this._z1));
  1203. while (q = octs.pop()) {
  1204. if (!callback(node = q.node, x0 = q.x0, y0 = q.y0, z0 = q.z0, x1 = q.x1, y1 = q.y1, z1 = q.z1) && node.length) {
  1205. var xm = (x0 + x1) / 2, ym = (y0 + y1) / 2, zm = (z0 + z1) / 2;
  1206. if (child = node[7]) octs.push(new Octant(child, xm, ym, zm, x1, y1, z1));
  1207. if (child = node[6]) octs.push(new Octant(child, x0, ym, zm, xm, y1, z1));
  1208. if (child = node[5]) octs.push(new Octant(child, xm, y0, zm, x1, ym, z1));
  1209. if (child = node[4]) octs.push(new Octant(child, x0, y0, zm, xm, ym, z1));
  1210. if (child = node[3]) octs.push(new Octant(child, xm, ym, z0, x1, y1, zm));
  1211. if (child = node[2]) octs.push(new Octant(child, x0, ym, z0, xm, y1, zm));
  1212. if (child = node[1]) octs.push(new Octant(child, xm, y0, z0, x1, ym, zm));
  1213. if (child = node[0]) octs.push(new Octant(child, x0, y0, z0, xm, ym, zm));
  1214. }
  1215. }
  1216. return this;
  1217. }
  1218. function tree_visitAfter(callback) {
  1219. var octs = [], next = [], q;
  1220. if (this._root) octs.push(new Octant(this._root, this._x0, this._y0, this._z0, this._x1, this._y1, this._z1));
  1221. while (q = octs.pop()) {
  1222. var node = q.node;
  1223. if (node.length) {
  1224. var child, x0 = q.x0, y0 = q.y0, z0 = q.z0, x1 = q.x1, y1 = q.y1, z1 = q.z1, xm = (x0 + x1) / 2, ym = (y0 + y1) / 2, zm = (z0 + z1) / 2;
  1225. if (child = node[0]) octs.push(new Octant(child, x0, y0, z0, xm, ym, zm));
  1226. if (child = node[1]) octs.push(new Octant(child, xm, y0, z0, x1, ym, zm));
  1227. if (child = node[2]) octs.push(new Octant(child, x0, ym, z0, xm, y1, zm));
  1228. if (child = node[3]) octs.push(new Octant(child, xm, ym, z0, x1, y1, zm));
  1229. if (child = node[4]) octs.push(new Octant(child, x0, y0, zm, xm, ym, z1));
  1230. if (child = node[5]) octs.push(new Octant(child, xm, y0, zm, x1, ym, z1));
  1231. if (child = node[6]) octs.push(new Octant(child, x0, ym, zm, xm, y1, z1));
  1232. if (child = node[7]) octs.push(new Octant(child, xm, ym, zm, x1, y1, z1));
  1233. }
  1234. next.push(q);
  1235. }
  1236. while (q = next.pop()) {
  1237. callback(q.node, q.x0, q.y0, q.z0, q.x1, q.y1, q.z1);
  1238. }
  1239. return this;
  1240. }
  1241. function defaultX(d) {
  1242. return d[0];
  1243. }
  1244. function tree_x(_) {
  1245. return arguments.length ? (this._x = _, this) : this._x;
  1246. }
  1247. function defaultY(d) {
  1248. return d[1];
  1249. }
  1250. function tree_y(_) {
  1251. return arguments.length ? (this._y = _, this) : this._y;
  1252. }
  1253. function defaultZ(d) {
  1254. return d[2];
  1255. }
  1256. function tree_z(_) {
  1257. return arguments.length ? (this._z = _, this) : this._z;
  1258. }
  1259. function octree(nodes, x, y, z) {
  1260. var tree = new Octree(x == null ? defaultX : x, y == null ? defaultY : y, z == null ? defaultZ : z, NaN, NaN, NaN, NaN, NaN, NaN);
  1261. return nodes == null ? tree : tree.addAll(nodes);
  1262. }
  1263. function Octree(x, y, z, x0, y0, z0, x1, y1, z1) {
  1264. this._x = x;
  1265. this._y = y;
  1266. this._z = z;
  1267. this._x0 = x0;
  1268. this._y0 = y0;
  1269. this._z0 = z0;
  1270. this._x1 = x1;
  1271. this._y1 = y1;
  1272. this._z1 = z1;
  1273. this._root = undefined;
  1274. }
  1275. function leaf_copy(leaf) {
  1276. var copy = {data: leaf.data}, next = copy;
  1277. while (leaf = leaf.next) next = next.next = {data: leaf.data};
  1278. return copy;
  1279. }
  1280. var treeProto = octree.prototype = Octree.prototype;
  1281. treeProto.copy = function() {
  1282. var copy = new Octree(this._x, this._y, this._z, this._x0, this._y0, this._z0, this._x1, this._y1, this._z1),
  1283. node = this._root,
  1284. nodes,
  1285. child;
  1286. if (!node) return copy;
  1287. if (!node.length) return copy._root = leaf_copy(node), copy;
  1288. nodes = [{source: node, target: copy._root = new Array(8)}];
  1289. while (node = nodes.pop()) {
  1290. for (var i = 0; i < 8; ++i) {
  1291. if (child = node.source[i]) {
  1292. if (child.length) nodes.push({source: child, target: node.target[i] = new Array(8)});
  1293. else node.target[i] = leaf_copy(child);
  1294. }
  1295. }
  1296. }
  1297. return copy;
  1298. };
  1299. treeProto.add = tree_add;
  1300. treeProto.addAll = addAll;
  1301. treeProto.cover = tree_cover;
  1302. treeProto.data = tree_data;
  1303. treeProto.extent = tree_extent;
  1304. treeProto.find = tree_find;
  1305. treeProto.remove = tree_remove;
  1306. treeProto.removeAll = removeAll;
  1307. treeProto.root = tree_root;
  1308. treeProto.size = tree_size;
  1309. treeProto.visit = tree_visit;
  1310. treeProto.visitAfter = tree_visitAfter;
  1311. treeProto.x = tree_x;
  1312. treeProto.y = tree_y;
  1313. treeProto.z = tree_z;
  1314. function constant(x) {
  1315. return function() {
  1316. return x;
  1317. };
  1318. }
  1319. function jiggle(random) {
  1320. return (random() - 0.5) * 1e-6;
  1321. }
  1322. function index$3(d) {
  1323. return d.index;
  1324. }
  1325. function find(nodeById, nodeId) {
  1326. var node = nodeById.get(nodeId);
  1327. if (!node) throw new Error("node not found: " + nodeId);
  1328. return node;
  1329. }
  1330. function d3ForceLink(links) {
  1331. var id = index$3,
  1332. strength = defaultStrength,
  1333. strengths,
  1334. distance = constant(30),
  1335. distances,
  1336. nodes,
  1337. nDim,
  1338. count,
  1339. bias,
  1340. random,
  1341. iterations = 1;
  1342. if (links == null) links = [];
  1343. function defaultStrength(link) {
  1344. return 1 / Math.min(count[link.source.index], count[link.target.index]);
  1345. }
  1346. function force(alpha) {
  1347. for (var k = 0, n = links.length; k < iterations; ++k) {
  1348. for (var i = 0, link, source, target, x = 0, y = 0, z = 0, l, b; i < n; ++i) {
  1349. link = links[i], source = link.source, target = link.target;
  1350. x = target.x + target.vx - source.x - source.vx || jiggle(random);
  1351. if (nDim > 1) { y = target.y + target.vy - source.y - source.vy || jiggle(random); }
  1352. if (nDim > 2) { z = target.z + target.vz - source.z - source.vz || jiggle(random); }
  1353. l = Math.sqrt(x * x + y * y + z * z);
  1354. l = (l - distances[i]) / l * alpha * strengths[i];
  1355. x *= l, y *= l, z *= l;
  1356. target.vx -= x * (b = bias[i]);
  1357. if (nDim > 1) { target.vy -= y * b; }
  1358. if (nDim > 2) { target.vz -= z * b; }
  1359. source.vx += x * (b = 1 - b);
  1360. if (nDim > 1) { source.vy += y * b; }
  1361. if (nDim > 2) { source.vz += z * b; }
  1362. }
  1363. }
  1364. }
  1365. function initialize() {
  1366. if (!nodes) return;
  1367. var i,
  1368. n = nodes.length,
  1369. m = links.length,
  1370. nodeById = new Map(nodes.map((d, i) => [id(d, i, nodes), d])),
  1371. link;
  1372. for (i = 0, count = new Array(n); i < m; ++i) {
  1373. link = links[i], link.index = i;
  1374. if (typeof link.source !== "object") link.source = find(nodeById, link.source);
  1375. if (typeof link.target !== "object") link.target = find(nodeById, link.target);
  1376. count[link.source.index] = (count[link.source.index] || 0) + 1;
  1377. count[link.target.index] = (count[link.target.index] || 0) + 1;
  1378. }
  1379. for (i = 0, bias = new Array(m); i < m; ++i) {
  1380. link = links[i], bias[i] = count[link.source.index] / (count[link.source.index] + count[link.target.index]);
  1381. }
  1382. strengths = new Array(m), initializeStrength();
  1383. distances = new Array(m), initializeDistance();
  1384. }
  1385. function initializeStrength() {
  1386. if (!nodes) return;
  1387. for (var i = 0, n = links.length; i < n; ++i) {
  1388. strengths[i] = +strength(links[i], i, links);
  1389. }
  1390. }
  1391. function initializeDistance() {
  1392. if (!nodes) return;
  1393. for (var i = 0, n = links.length; i < n; ++i) {
  1394. distances[i] = +distance(links[i], i, links);
  1395. }
  1396. }
  1397. force.initialize = function(_nodes, ...args) {
  1398. nodes = _nodes;
  1399. random = args.find(arg => typeof arg === 'function') || Math.random;
  1400. nDim = args.find(arg => [1, 2, 3].includes(arg)) || 2;
  1401. initialize();
  1402. };
  1403. force.links = function(_) {
  1404. return arguments.length ? (links = _, initialize(), force) : links;
  1405. };
  1406. force.id = function(_) {
  1407. return arguments.length ? (id = _, force) : id;
  1408. };
  1409. force.iterations = function(_) {
  1410. return arguments.length ? (iterations = +_, force) : iterations;
  1411. };
  1412. force.strength = function(_) {
  1413. return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initializeStrength(), force) : strength;
  1414. };
  1415. force.distance = function(_) {
  1416. return arguments.length ? (distance = typeof _ === "function" ? _ : constant(+_), initializeDistance(), force) : distance;
  1417. };
  1418. return force;
  1419. }
  1420. var noop$1 = {value: () => {}};
  1421. function dispatch() {
  1422. for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) {
  1423. if (!(t = arguments[i] + "") || (t in _) || /[\s.]/.test(t)) throw new Error("illegal type: " + t);
  1424. _[t] = [];
  1425. }
  1426. return new Dispatch(_);
  1427. }
  1428. function Dispatch(_) {
  1429. this._ = _;
  1430. }
  1431. function parseTypenames(typenames, types) {
  1432. return typenames.trim().split(/^|\s+/).map(function(t) {
  1433. var name = "", i = t.indexOf(".");
  1434. if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i);
  1435. if (t && !types.hasOwnProperty(t)) throw new Error("unknown type: " + t);
  1436. return {type: t, name: name};
  1437. });
  1438. }
  1439. Dispatch.prototype = dispatch.prototype = {
  1440. constructor: Dispatch,
  1441. on: function(typename, callback) {
  1442. var _ = this._,
  1443. T = parseTypenames(typename + "", _),
  1444. t,
  1445. i = -1,
  1446. n = T.length;
  1447. // If no callback was specified, return the callback of the given type and name.
  1448. if (arguments.length < 2) {
  1449. while (++i < n) if ((t = (typename = T[i]).type) && (t = get(_[t], typename.name))) return t;
  1450. return;
  1451. }
  1452. // If a type was specified, set the callback for the given type and name.
  1453. // Otherwise, if a null callback was specified, remove callbacks of the given name.
  1454. if (callback != null && typeof callback !== "function") throw new Error("invalid callback: " + callback);
  1455. while (++i < n) {
  1456. if (t = (typename = T[i]).type) _[t] = set(_[t], typename.name, callback);
  1457. else if (callback == null) for (t in _) _[t] = set(_[t], typename.name, null);
  1458. }
  1459. return this;
  1460. },
  1461. copy: function() {
  1462. var copy = {}, _ = this._;
  1463. for (var t in _) copy[t] = _[t].slice();
  1464. return new Dispatch(copy);
  1465. },
  1466. call: function(type, that) {
  1467. if ((n = arguments.length - 2) > 0) for (var args = new Array(n), i = 0, n, t; i < n; ++i) args[i] = arguments[i + 2];
  1468. if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type);
  1469. for (t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args);
  1470. },
  1471. apply: function(type, that, args) {
  1472. if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type);
  1473. for (var t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args);
  1474. }
  1475. };
  1476. function get(type, name) {
  1477. for (var i = 0, n = type.length, c; i < n; ++i) {
  1478. if ((c = type[i]).name === name) {
  1479. return c.value;
  1480. }
  1481. }
  1482. }
  1483. function set(type, name, callback) {
  1484. for (var i = 0, n = type.length; i < n; ++i) {
  1485. if (type[i].name === name) {
  1486. type[i] = noop$1, type = type.slice(0, i).concat(type.slice(i + 1));
  1487. break;
  1488. }
  1489. }
  1490. if (callback != null) type.push({name: name, value: callback});
  1491. return type;
  1492. }
  1493. var frame = 0, // is an animation frame pending?
  1494. timeout = 0, // is a timeout pending?
  1495. interval = 0, // are any timers active?
  1496. pokeDelay = 1000, // how frequently we check for clock skew
  1497. taskHead,
  1498. taskTail,
  1499. clockLast = 0,
  1500. clockNow = 0,
  1501. clockSkew = 0,
  1502. clock = typeof performance === "object" && performance.now ? performance : Date,
  1503. setFrame = typeof window === "object" && window.requestAnimationFrame ? window.requestAnimationFrame.bind(window) : function(f) { setTimeout(f, 17); };
  1504. function now() {
  1505. return clockNow || (setFrame(clearNow), clockNow = clock.now() + clockSkew);
  1506. }
  1507. function clearNow() {
  1508. clockNow = 0;
  1509. }
  1510. function Timer() {
  1511. this._call =
  1512. this._time =
  1513. this._next = null;
  1514. }
  1515. Timer.prototype = timer.prototype = {
  1516. constructor: Timer,
  1517. restart: function(callback, delay, time) {
  1518. if (typeof callback !== "function") throw new TypeError("callback is not a function");
  1519. time = (time == null ? now() : +time) + (delay == null ? 0 : +delay);
  1520. if (!this._next && taskTail !== this) {
  1521. if (taskTail) taskTail._next = this;
  1522. else taskHead = this;
  1523. taskTail = this;
  1524. }
  1525. this._call = callback;
  1526. this._time = time;
  1527. sleep();
  1528. },
  1529. stop: function() {
  1530. if (this._call) {
  1531. this._call = null;
  1532. this._time = Infinity;
  1533. sleep();
  1534. }
  1535. }
  1536. };
  1537. function timer(callback, delay, time) {
  1538. var t = new Timer;
  1539. t.restart(callback, delay, time);
  1540. return t;
  1541. }
  1542. function timerFlush() {
  1543. now(); // Get the current time, if not already set.
  1544. ++frame; // Pretend we’ve set an alarm, if we haven’t already.
  1545. var t = taskHead, e;
  1546. while (t) {
  1547. if ((e = clockNow - t._time) >= 0) t._call.call(undefined, e);
  1548. t = t._next;
  1549. }
  1550. --frame;
  1551. }
  1552. function wake() {
  1553. clockNow = (clockLast = clock.now()) + clockSkew;
  1554. frame = timeout = 0;
  1555. try {
  1556. timerFlush();
  1557. } finally {
  1558. frame = 0;
  1559. nap();
  1560. clockNow = 0;
  1561. }
  1562. }
  1563. function poke() {
  1564. var now = clock.now(), delay = now - clockLast;
  1565. if (delay > pokeDelay) clockSkew -= delay, clockLast = now;
  1566. }
  1567. function nap() {
  1568. var t0, t1 = taskHead, t2, time = Infinity;
  1569. while (t1) {
  1570. if (t1._call) {
  1571. if (time > t1._time) time = t1._time;
  1572. t0 = t1, t1 = t1._next;
  1573. } else {
  1574. t2 = t1._next, t1._next = null;
  1575. t1 = t0 ? t0._next = t2 : taskHead = t2;
  1576. }
  1577. }
  1578. taskTail = t0;
  1579. sleep(time);
  1580. }
  1581. function sleep(time) {
  1582. if (frame) return; // Soonest alarm already set, or will be.
  1583. if (timeout) timeout = clearTimeout(timeout);
  1584. var delay = time - clockNow; // Strictly less than if we recomputed clockNow.
  1585. if (delay > 24) {
  1586. if (time < Infinity) timeout = setTimeout(wake, time - clock.now() - clockSkew);
  1587. if (interval) interval = clearInterval(interval);
  1588. } else {
  1589. if (!interval) clockLast = clock.now(), interval = setInterval(poke, pokeDelay);
  1590. frame = 1, setFrame(wake);
  1591. }
  1592. }
  1593. // https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use
  1594. const a = 1664525;
  1595. const c = 1013904223;
  1596. const m = 4294967296; // 2^32
  1597. function lcg() {
  1598. let s = 1;
  1599. return () => (s = (a * s + c) % m) / m;
  1600. }
  1601. var MAX_DIMENSIONS = 3;
  1602. function x(d) {
  1603. return d.x;
  1604. }
  1605. function y(d) {
  1606. return d.y;
  1607. }
  1608. function z(d) {
  1609. return d.z;
  1610. }
  1611. var initialRadius = 10,
  1612. initialAngleRoll = Math.PI * (3 - Math.sqrt(5)), // Golden ratio angle
  1613. initialAngleYaw = Math.PI * 20 / (9 + Math.sqrt(221)); // Markov irrational number
  1614. function d3ForceSimulation(nodes, numDimensions) {
  1615. numDimensions = numDimensions || 2;
  1616. var nDim = Math.min(MAX_DIMENSIONS, Math.max(1, Math.round(numDimensions))),
  1617. simulation,
  1618. alpha = 1,
  1619. alphaMin = 0.001,
  1620. alphaDecay = 1 - Math.pow(alphaMin, 1 / 300),
  1621. alphaTarget = 0,
  1622. velocityDecay = 0.6,
  1623. forces = new Map(),
  1624. stepper = timer(step),
  1625. event = dispatch("tick", "end"),
  1626. random = lcg();
  1627. if (nodes == null) nodes = [];
  1628. function step() {
  1629. tick();
  1630. event.call("tick", simulation);
  1631. if (alpha < alphaMin) {
  1632. stepper.stop();
  1633. event.call("end", simulation);
  1634. }
  1635. }
  1636. function tick(iterations) {
  1637. var i, n = nodes.length, node;
  1638. if (iterations === undefined) iterations = 1;
  1639. for (var k = 0; k < iterations; ++k) {
  1640. alpha += (alphaTarget - alpha) * alphaDecay;
  1641. forces.forEach(function (force) {
  1642. force(alpha);
  1643. });
  1644. for (i = 0; i < n; ++i) {
  1645. node = nodes[i];
  1646. if (node.fx == null) node.x += node.vx *= velocityDecay;
  1647. else node.x = node.fx, node.vx = 0;
  1648. if (nDim > 1) {
  1649. if (node.fy == null) node.y += node.vy *= velocityDecay;
  1650. else node.y = node.fy, node.vy = 0;
  1651. }
  1652. if (nDim > 2) {
  1653. if (node.fz == null) node.z += node.vz *= velocityDecay;
  1654. else node.z = node.fz, node.vz = 0;
  1655. }
  1656. }
  1657. }
  1658. return simulation;
  1659. }
  1660. function initializeNodes() {
  1661. for (var i = 0, n = nodes.length, node; i < n; ++i) {
  1662. node = nodes[i], node.index = i;
  1663. if (node.fx != null) node.x = node.fx;
  1664. if (node.fy != null) node.y = node.fy;
  1665. if (node.fz != null) node.z = node.fz;
  1666. if (isNaN(node.x) || (nDim > 1 && isNaN(node.y)) || (nDim > 2 && isNaN(node.z))) {
  1667. var radius = initialRadius * (nDim > 2 ? Math.cbrt(0.5 + i) : (nDim > 1 ? Math.sqrt(0.5 + i) : i)),
  1668. rollAngle = i * initialAngleRoll,
  1669. yawAngle = i * initialAngleYaw;
  1670. if (nDim === 1) {
  1671. node.x = radius;
  1672. } else if (nDim === 2) {
  1673. node.x = radius * Math.cos(rollAngle);
  1674. node.y = radius * Math.sin(rollAngle);
  1675. } else { // 3 dimensions: use spherical distribution along 2 irrational number angles
  1676. node.x = radius * Math.sin(rollAngle) * Math.cos(yawAngle);
  1677. node.y = radius * Math.cos(rollAngle);
  1678. node.z = radius * Math.sin(rollAngle) * Math.sin(yawAngle);
  1679. }
  1680. }
  1681. if (isNaN(node.vx) || (nDim > 1 && isNaN(node.vy)) || (nDim > 2 && isNaN(node.vz))) {
  1682. node.vx = 0;
  1683. if (nDim > 1) { node.vy = 0; }
  1684. if (nDim > 2) { node.vz = 0; }
  1685. }
  1686. }
  1687. }
  1688. function initializeForce(force) {
  1689. if (force.initialize) force.initialize(nodes, random, nDim);
  1690. return force;
  1691. }
  1692. initializeNodes();
  1693. return simulation = {
  1694. tick: tick,
  1695. restart: function() {
  1696. return stepper.restart(step), simulation;
  1697. },
  1698. stop: function() {
  1699. return stepper.stop(), simulation;
  1700. },
  1701. numDimensions: function(_) {
  1702. return arguments.length
  1703. ? (nDim = Math.min(MAX_DIMENSIONS, Math.max(1, Math.round(_))), forces.forEach(initializeForce), simulation)
  1704. : nDim;
  1705. },
  1706. nodes: function(_) {
  1707. return arguments.length ? (nodes = _, initializeNodes(), forces.forEach(initializeForce), simulation) : nodes;
  1708. },
  1709. alpha: function(_) {
  1710. return arguments.length ? (alpha = +_, simulation) : alpha;
  1711. },
  1712. alphaMin: function(_) {
  1713. return arguments.length ? (alphaMin = +_, simulation) : alphaMin;
  1714. },
  1715. alphaDecay: function(_) {
  1716. return arguments.length ? (alphaDecay = +_, simulation) : +alphaDecay;
  1717. },
  1718. alphaTarget: function(_) {
  1719. return arguments.length ? (alphaTarget = +_, simulation) : alphaTarget;
  1720. },
  1721. velocityDecay: function(_) {
  1722. return arguments.length ? (velocityDecay = 1 - _, simulation) : 1 - velocityDecay;
  1723. },
  1724. randomSource: function(_) {
  1725. return arguments.length ? (random = _, forces.forEach(initializeForce), simulation) : random;
  1726. },
  1727. force: function(name, _) {
  1728. return arguments.length > 1 ? ((_ == null ? forces.delete(name) : forces.set(name, initializeForce(_))), simulation) : forces.get(name);
  1729. },
  1730. find: function() {
  1731. var args = Array.prototype.slice.call(arguments);
  1732. var x = args.shift() || 0,
  1733. y = (nDim > 1 ? args.shift() : null) || 0,
  1734. z = (nDim > 2 ? args.shift() : null) || 0,
  1735. radius = args.shift() || Infinity;
  1736. var i = 0,
  1737. n = nodes.length,
  1738. dx,
  1739. dy,
  1740. dz,
  1741. d2,
  1742. node,
  1743. closest;
  1744. radius *= radius;
  1745. for (i = 0; i < n; ++i) {
  1746. node = nodes[i];
  1747. dx = x - node.x;
  1748. dy = y - (node.y || 0);
  1749. dz = z - (node.z ||0);
  1750. d2 = dx * dx + dy * dy + dz * dz;
  1751. if (d2 < radius) closest = node, radius = d2;
  1752. }
  1753. return closest;
  1754. },
  1755. on: function(name, _) {
  1756. return arguments.length > 1 ? (event.on(name, _), simulation) : event.on(name);
  1757. }
  1758. };
  1759. }
  1760. function d3ForceManyBody() {
  1761. var nodes,
  1762. nDim,
  1763. node,
  1764. random,
  1765. alpha,
  1766. strength = constant(-30),
  1767. strengths,
  1768. distanceMin2 = 1,
  1769. distanceMax2 = Infinity,
  1770. theta2 = 0.81;
  1771. function force(_) {
  1772. var i,
  1773. n = nodes.length,
  1774. tree =
  1775. (nDim === 1 ? binarytree(nodes, x)
  1776. :(nDim === 2 ? quadtree(nodes, x, y)
  1777. :(nDim === 3 ? octree(nodes, x, y, z)
  1778. :null
  1779. ))).visitAfter(accumulate);
  1780. for (alpha = _, i = 0; i < n; ++i) node = nodes[i], tree.visit(apply);
  1781. }
  1782. function initialize() {
  1783. if (!nodes) return;
  1784. var i, n = nodes.length, node;
  1785. strengths = new Array(n);
  1786. for (i = 0; i < n; ++i) node = nodes[i], strengths[node.index] = +strength(node, i, nodes);
  1787. }
  1788. function accumulate(treeNode) {
  1789. var strength = 0, q, c, weight = 0, x, y, z, i;
  1790. var numChildren = treeNode.length;
  1791. // For internal nodes, accumulate forces from children.
  1792. if (numChildren) {
  1793. for (x = y = z = i = 0; i < numChildren; ++i) {
  1794. if ((q = treeNode[i]) && (c = Math.abs(q.value))) {
  1795. strength += q.value, weight += c, x += c * (q.x || 0), y += c * (q.y || 0), z += c * (q.z || 0);
  1796. }
  1797. }
  1798. strength *= Math.sqrt(4 / numChildren); // scale accumulated strength according to number of dimensions
  1799. treeNode.x = x / weight;
  1800. if (nDim > 1) { treeNode.y = y / weight; }
  1801. if (nDim > 2) { treeNode.z = z / weight; }
  1802. }
  1803. // For leaf nodes, accumulate forces from coincident nodes.
  1804. else {
  1805. q = treeNode;
  1806. q.x = q.data.x;
  1807. if (nDim > 1) { q.y = q.data.y; }
  1808. if (nDim > 2) { q.z = q.data.z; }
  1809. do strength += strengths[q.data.index];
  1810. while (q = q.next);
  1811. }
  1812. treeNode.value = strength;
  1813. }
  1814. function apply(treeNode, x1, arg1, arg2, arg3) {
  1815. if (!treeNode.value) return true;
  1816. var x2 = [arg1, arg2, arg3][nDim-1];
  1817. var x = treeNode.x - node.x,
  1818. y = (nDim > 1 ? treeNode.y - node.y : 0),
  1819. z = (nDim > 2 ? treeNode.z - node.z : 0),
  1820. w = x2 - x1,
  1821. l = x * x + y * y + z * z;
  1822. // Apply the Barnes-Hut approximation if possible.
  1823. // Limit forces for very close nodes; randomize direction if coincident.
  1824. if (w * w / theta2 < l) {
  1825. if (l < distanceMax2) {
  1826. if (x === 0) x = jiggle(random), l += x * x;
  1827. if (nDim > 1 && y === 0) y = jiggle(random), l += y * y;
  1828. if (nDim > 2 && z === 0) z = jiggle(random), l += z * z;
  1829. if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l);
  1830. node.vx += x * treeNode.value * alpha / l;
  1831. if (nDim > 1) { node.vy += y * treeNode.value * alpha / l; }
  1832. if (nDim > 2) { node.vz += z * treeNode.value * alpha / l; }
  1833. }
  1834. return true;
  1835. }
  1836. // Otherwise, process points directly.
  1837. else if (treeNode.length || l >= distanceMax2) return;
  1838. // Limit forces for very close nodes; randomize direction if coincident.
  1839. if (treeNode.data !== node || treeNode.next) {
  1840. if (x === 0) x = jiggle(random), l += x * x;
  1841. if (nDim > 1 && y === 0) y = jiggle(random), l += y * y;
  1842. if (nDim > 2 && z === 0) z = jiggle(random), l += z * z;
  1843. if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l);
  1844. }
  1845. do if (treeNode.data !== node) {
  1846. w = strengths[treeNode.data.index] * alpha / l;
  1847. node.vx += x * w;
  1848. if (nDim > 1) { node.vy += y * w; }
  1849. if (nDim > 2) { node.vz += z * w; }
  1850. } while (treeNode = treeNode.next);
  1851. }
  1852. force.initialize = function(_nodes, ...args) {
  1853. nodes = _nodes;
  1854. random = args.find(arg => typeof arg === 'function') || Math.random;
  1855. nDim = args.find(arg => [1, 2, 3].includes(arg)) || 2;
  1856. initialize();
  1857. };
  1858. force.strength = function(_) {
  1859. return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initialize(), force) : strength;
  1860. };
  1861. force.distanceMin = function(_) {
  1862. return arguments.length ? (distanceMin2 = _ * _, force) : Math.sqrt(distanceMin2);
  1863. };
  1864. force.distanceMax = function(_) {
  1865. return arguments.length ? (distanceMax2 = _ * _, force) : Math.sqrt(distanceMax2);
  1866. };
  1867. force.theta = function(_) {
  1868. return arguments.length ? (theta2 = _ * _, force) : Math.sqrt(theta2);
  1869. };
  1870. return force;
  1871. }
  1872. function d3ForceRadial(radius, x, y, z) {
  1873. var nodes,
  1874. nDim,
  1875. strength = constant(0.1),
  1876. strengths,
  1877. radiuses;
  1878. if (typeof radius !== "function") radius = constant(+radius);
  1879. if (x == null) x = 0;
  1880. if (y == null) y = 0;
  1881. if (z == null) z = 0;
  1882. function force(alpha) {
  1883. for (var i = 0, n = nodes.length; i < n; ++i) {
  1884. var node = nodes[i],
  1885. dx = node.x - x || 1e-6,
  1886. dy = (node.y || 0) - y || 1e-6,
  1887. dz = (node.z || 0) - z || 1e-6,
  1888. r = Math.sqrt(dx * dx + dy * dy + dz * dz),
  1889. k = (radiuses[i] - r) * strengths[i] * alpha / r;
  1890. node.vx += dx * k;
  1891. if (nDim>1) { node.vy += dy * k; }
  1892. if (nDim>2) { node.vz += dz * k; }
  1893. }
  1894. }
  1895. function initialize() {
  1896. if (!nodes) return;
  1897. var i, n = nodes.length;
  1898. strengths = new Array(n);
  1899. radiuses = new Array(n);
  1900. for (i = 0; i < n; ++i) {
  1901. radiuses[i] = +radius(nodes[i], i, nodes);
  1902. strengths[i] = isNaN(radiuses[i]) ? 0 : +strength(nodes[i], i, nodes);
  1903. }
  1904. }
  1905. force.initialize = function(initNodes, ...args) {
  1906. nodes = initNodes;
  1907. nDim = args.find(arg => [1, 2, 3].includes(arg)) || 2;
  1908. initialize();
  1909. };
  1910. force.strength = function(_) {
  1911. return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initialize(), force) : strength;
  1912. };
  1913. force.radius = function(_) {
  1914. return arguments.length ? (radius = typeof _ === "function" ? _ : constant(+_), initialize(), force) : radius;
  1915. };
  1916. force.x = function(_) {
  1917. return arguments.length ? (x = +_, force) : x;
  1918. };
  1919. force.y = function(_) {
  1920. return arguments.length ? (y = +_, force) : y;
  1921. };
  1922. force.z = function(_) {
  1923. return arguments.length ? (z = +_, force) : z;
  1924. };
  1925. return force;
  1926. }
  1927. var ngraph_events = function eventify(subject) {
  1928. validateSubject(subject);
  1929. var eventsStorage = createEventsStorage(subject);
  1930. subject.on = eventsStorage.on;
  1931. subject.off = eventsStorage.off;
  1932. subject.fire = eventsStorage.fire;
  1933. return subject;
  1934. };
  1935. function createEventsStorage(subject) {
  1936. // Store all event listeners to this hash. Key is event name, value is array
  1937. // of callback records.
  1938. //
  1939. // A callback record consists of callback function and its optional context:
  1940. // { 'eventName' => [{callback: function, ctx: object}] }
  1941. var registeredEvents = Object.create(null);
  1942. return {
  1943. on: function (eventName, callback, ctx) {
  1944. if (typeof callback !== 'function') {
  1945. throw new Error('callback is expected to be a function');
  1946. }
  1947. var handlers = registeredEvents[eventName];
  1948. if (!handlers) {
  1949. handlers = registeredEvents[eventName] = [];
  1950. }
  1951. handlers.push({callback: callback, ctx: ctx});
  1952. return subject;
  1953. },
  1954. off: function (eventName, callback) {
  1955. var wantToRemoveAll = (typeof eventName === 'undefined');
  1956. if (wantToRemoveAll) {
  1957. // Killing old events storage should be enough in this case:
  1958. registeredEvents = Object.create(null);
  1959. return subject;
  1960. }
  1961. if (registeredEvents[eventName]) {
  1962. var deleteAllCallbacksForEvent = (typeof callback !== 'function');
  1963. if (deleteAllCallbacksForEvent) {
  1964. delete registeredEvents[eventName];
  1965. } else {
  1966. var callbacks = registeredEvents[eventName];
  1967. for (var i = 0; i < callbacks.length; ++i) {
  1968. if (callbacks[i].callback === callback) {
  1969. callbacks.splice(i, 1);
  1970. }
  1971. }
  1972. }
  1973. }
  1974. return subject;
  1975. },
  1976. fire: function (eventName) {
  1977. var callbacks = registeredEvents[eventName];
  1978. if (!callbacks) {
  1979. return subject;
  1980. }
  1981. var fireArguments;
  1982. if (arguments.length > 1) {
  1983. fireArguments = Array.prototype.splice.call(arguments, 1);
  1984. }
  1985. for(var i = 0; i < callbacks.length; ++i) {
  1986. var callbackInfo = callbacks[i];
  1987. callbackInfo.callback.apply(callbackInfo.ctx, fireArguments);
  1988. }
  1989. return subject;
  1990. }
  1991. };
  1992. }
  1993. function validateSubject(subject) {
  1994. if (!subject) {
  1995. throw new Error('Eventify cannot use falsy object as events subject');
  1996. }
  1997. var reservedWords = ['on', 'fire', 'off'];
  1998. for (var i = 0; i < reservedWords.length; ++i) {
  1999. if (subject.hasOwnProperty(reservedWords[i])) {
  2000. throw new Error("Subject cannot be eventified, since it already has property '" + reservedWords[i] + "'");
  2001. }
  2002. }
  2003. }
  2004. /**
  2005. * @fileOverview Contains definition of the core graph object.
  2006. */
  2007. // TODO: need to change storage layer:
  2008. // 1. Be able to get all nodes O(1)
  2009. // 2. Be able to get number of links O(1)
  2010. /**
  2011. * @example
  2012. * var graph = require('ngraph.graph')();
  2013. * graph.addNode(1); // graph has one node.
  2014. * graph.addLink(2, 3); // now graph contains three nodes and one link.
  2015. *
  2016. */
  2017. var ngraph_graph = createGraph;
  2018. var eventify$1 = ngraph_events;
  2019. /**
  2020. * Creates a new graph
  2021. */
  2022. function createGraph(options) {
  2023. // Graph structure is maintained as dictionary of nodes
  2024. // and array of links. Each node has 'links' property which
  2025. // hold all links related to that node. And general links
  2026. // array is used to speed up all links enumeration. This is inefficient
  2027. // in terms of memory, but simplifies coding.
  2028. options = options || {};
  2029. if ('uniqueLinkId' in options) {
  2030. console.warn(
  2031. 'ngraph.graph: Starting from version 0.14 `uniqueLinkId` is deprecated.\n' +
  2032. 'Use `multigraph` option instead\n',
  2033. '\n',
  2034. 'Note: there is also change in default behavior: From now on each graph\n'+
  2035. 'is considered to be not a multigraph by default (each edge is unique).'
  2036. );
  2037. options.multigraph = options.uniqueLinkId;
  2038. }
  2039. // Dear reader, the non-multigraphs do not guarantee that there is only
  2040. // one link for a given pair of node. When this option is set to false
  2041. // we can save some memory and CPU (18% faster for non-multigraph);
  2042. if (options.multigraph === undefined) options.multigraph = false;
  2043. if (typeof Map !== 'function') {
  2044. // TODO: Should we polyfill it ourselves? We don't use much operations there..
  2045. throw new Error('ngraph.graph requires `Map` to be defined. Please polyfill it before using ngraph');
  2046. }
  2047. var nodes = new Map();
  2048. var links = [],
  2049. // Hash of multi-edges. Used to track ids of edges between same nodes
  2050. multiEdges = {},
  2051. suspendEvents = 0,
  2052. createLink = options.multigraph ? createUniqueLink : createSingleLink,
  2053. // Our graph API provides means to listen to graph changes. Users can subscribe
  2054. // to be notified about changes in the graph by using `on` method. However
  2055. // in some cases they don't use it. To avoid unnecessary memory consumption
  2056. // we will not record graph changes until we have at least one subscriber.
  2057. // Code below supports this optimization.
  2058. //
  2059. // Accumulates all changes made during graph updates.
  2060. // Each change element contains:
  2061. // changeType - one of the strings: 'add', 'remove' or 'update';
  2062. // node - if change is related to node this property is set to changed graph's node;
  2063. // link - if change is related to link this property is set to changed graph's link;
  2064. changes = [],
  2065. recordLinkChange = noop,
  2066. recordNodeChange = noop,
  2067. enterModification = noop,
  2068. exitModification = noop;
  2069. // this is our public API:
  2070. var graphPart = {
  2071. /**
  2072. * Adds node to the graph. If node with given id already exists in the graph
  2073. * its data is extended with whatever comes in 'data' argument.
  2074. *
  2075. * @param nodeId the node's identifier. A string or number is preferred.
  2076. * @param [data] additional data for the node being added. If node already
  2077. * exists its data object is augmented with the new one.
  2078. *
  2079. * @return {node} The newly added node or node with given id if it already exists.
  2080. */
  2081. addNode: addNode,
  2082. /**
  2083. * Adds a link to the graph. The function always create a new
  2084. * link between two nodes. If one of the nodes does not exists
  2085. * a new node is created.
  2086. *
  2087. * @param fromId link start node id;
  2088. * @param toId link end node id;
  2089. * @param [data] additional data to be set on the new link;
  2090. *
  2091. * @return {link} The newly created link
  2092. */
  2093. addLink: addLink,
  2094. /**
  2095. * Removes link from the graph. If link does not exist does nothing.
  2096. *
  2097. * @param link - object returned by addLink() or getLinks() methods.
  2098. *
  2099. * @returns true if link was removed; false otherwise.
  2100. */
  2101. removeLink: removeLink,
  2102. /**
  2103. * Removes node with given id from the graph. If node does not exist in the graph
  2104. * does nothing.
  2105. *
  2106. * @param nodeId node's identifier passed to addNode() function.
  2107. *
  2108. * @returns true if node was removed; false otherwise.
  2109. */
  2110. removeNode: removeNode,
  2111. /**
  2112. * Gets node with given identifier. If node does not exist undefined value is returned.
  2113. *
  2114. * @param nodeId requested node identifier;
  2115. *
  2116. * @return {node} in with requested identifier or undefined if no such node exists.
  2117. */
  2118. getNode: getNode,
  2119. /**
  2120. * Gets number of nodes in this graph.
  2121. *
  2122. * @return number of nodes in the graph.
  2123. */
  2124. getNodeCount: getNodeCount,
  2125. /**
  2126. * Gets total number of links in the graph.
  2127. */
  2128. getLinkCount: getLinkCount,
  2129. /**
  2130. * Synonym for `getLinkCount()`
  2131. */
  2132. getLinksCount: getLinkCount,
  2133. /**
  2134. * Synonym for `getNodeCount()`
  2135. */
  2136. getNodesCount: getNodeCount,
  2137. /**
  2138. * Gets all links (inbound and outbound) from the node with given id.
  2139. * If node with given id is not found null is returned.
  2140. *
  2141. * @param nodeId requested node identifier.
  2142. *
  2143. * @return Array of links from and to requested node if such node exists;
  2144. * otherwise null is returned.
  2145. */
  2146. getLinks: getLinks,
  2147. /**
  2148. * Invokes callback on each node of the graph.
  2149. *
  2150. * @param {Function(node)} callback Function to be invoked. The function
  2151. * is passed one argument: visited node.
  2152. */
  2153. forEachNode: forEachNode,
  2154. /**
  2155. * Invokes callback on every linked (adjacent) node to the given one.
  2156. *
  2157. * @param nodeId Identifier of the requested node.
  2158. * @param {Function(node, link)} callback Function to be called on all linked nodes.
  2159. * The function is passed two parameters: adjacent node and link object itself.
  2160. * @param oriented if true graph treated as oriented.
  2161. */
  2162. forEachLinkedNode: forEachLinkedNode,
  2163. /**
  2164. * Enumerates all links in the graph
  2165. *
  2166. * @param {Function(link)} callback Function to be called on all links in the graph.
  2167. * The function is passed one parameter: graph's link object.
  2168. *
  2169. * Link object contains at least the following fields:
  2170. * fromId - node id where link starts;
  2171. * toId - node id where link ends,
  2172. * data - additional data passed to graph.addLink() method.
  2173. */
  2174. forEachLink: forEachLink,
  2175. /**
  2176. * Suspend all notifications about graph changes until
  2177. * endUpdate is called.
  2178. */
  2179. beginUpdate: enterModification,
  2180. /**
  2181. * Resumes all notifications about graph changes and fires
  2182. * graph 'changed' event in case there are any pending changes.
  2183. */
  2184. endUpdate: exitModification,
  2185. /**
  2186. * Removes all nodes and links from the graph.
  2187. */
  2188. clear: clear,
  2189. /**
  2190. * Detects whether there is a link between two nodes.
  2191. * Operation complexity is O(n) where n - number of links of a node.
  2192. * NOTE: this function is synonim for getLink()
  2193. *
  2194. * @returns link if there is one. null otherwise.
  2195. */
  2196. hasLink: getLink,
  2197. /**
  2198. * Detects whether there is a node with given id
  2199. *
  2200. * Operation complexity is O(1)
  2201. * NOTE: this function is synonim for getNode()
  2202. *
  2203. * @returns node if there is one; Falsy value otherwise.
  2204. */
  2205. hasNode: getNode,
  2206. /**
  2207. * Gets an edge between two nodes.
  2208. * Operation complexity is O(n) where n - number of links of a node.
  2209. *
  2210. * @param {string} fromId link start identifier
  2211. * @param {string} toId link end identifier
  2212. *
  2213. * @returns link if there is one. null otherwise.
  2214. */
  2215. getLink: getLink
  2216. };
  2217. // this will add `on()` and `fire()` methods.
  2218. eventify$1(graphPart);
  2219. monitorSubscribers();
  2220. return graphPart;
  2221. function monitorSubscribers() {
  2222. var realOn = graphPart.on;
  2223. // replace real `on` with our temporary on, which will trigger change
  2224. // modification monitoring:
  2225. graphPart.on = on;
  2226. function on() {
  2227. // now it's time to start tracking stuff:
  2228. graphPart.beginUpdate = enterModification = enterModificationReal;
  2229. graphPart.endUpdate = exitModification = exitModificationReal;
  2230. recordLinkChange = recordLinkChangeReal;
  2231. recordNodeChange = recordNodeChangeReal;
  2232. // this will replace current `on` method with real pub/sub from `eventify`.
  2233. graphPart.on = realOn;
  2234. // delegate to real `on` handler:
  2235. return realOn.apply(graphPart, arguments);
  2236. }
  2237. }
  2238. function recordLinkChangeReal(link, changeType) {
  2239. changes.push({
  2240. link: link,
  2241. changeType: changeType
  2242. });
  2243. }
  2244. function recordNodeChangeReal(node, changeType) {
  2245. changes.push({
  2246. node: node,
  2247. changeType: changeType
  2248. });
  2249. }
  2250. function addNode(nodeId, data) {
  2251. if (nodeId === undefined) {
  2252. throw new Error('Invalid node identifier');
  2253. }
  2254. enterModification();
  2255. var node = getNode(nodeId);
  2256. if (!node) {
  2257. node = new Node(nodeId, data);
  2258. recordNodeChange(node, 'add');
  2259. } else {
  2260. node.data = data;
  2261. recordNodeChange(node, 'update');
  2262. }
  2263. nodes.set(nodeId, node);
  2264. exitModification();
  2265. return node;
  2266. }
  2267. function getNode(nodeId) {
  2268. return nodes.get(nodeId);
  2269. }
  2270. function removeNode(nodeId) {
  2271. var node = getNode(nodeId);
  2272. if (!node) {
  2273. return false;
  2274. }
  2275. enterModification();
  2276. var prevLinks = node.links;
  2277. if (prevLinks) {
  2278. node.links = null;
  2279. for(var i = 0; i < prevLinks.length; ++i) {
  2280. removeLink(prevLinks[i]);
  2281. }
  2282. }
  2283. nodes.delete(nodeId);
  2284. recordNodeChange(node, 'remove');
  2285. exitModification();
  2286. return true;
  2287. }
  2288. function addLink(fromId, toId, data) {
  2289. enterModification();
  2290. var fromNode = getNode(fromId) || addNode(fromId);
  2291. var toNode = getNode(toId) || addNode(toId);
  2292. var link = createLink(fromId, toId, data);
  2293. links.push(link);
  2294. // TODO: this is not cool. On large graphs potentially would consume more memory.
  2295. addLinkToNode(fromNode, link);
  2296. if (fromId !== toId) {
  2297. // make sure we are not duplicating links for self-loops
  2298. addLinkToNode(toNode, link);
  2299. }
  2300. recordLinkChange(link, 'add');
  2301. exitModification();
  2302. return link;
  2303. }
  2304. function createSingleLink(fromId, toId, data) {
  2305. var linkId = makeLinkId(fromId, toId);
  2306. return new Link(fromId, toId, data, linkId);
  2307. }
  2308. function createUniqueLink(fromId, toId, data) {
  2309. // TODO: Get rid of this method.
  2310. var linkId = makeLinkId(fromId, toId);
  2311. var isMultiEdge = multiEdges.hasOwnProperty(linkId);
  2312. if (isMultiEdge || getLink(fromId, toId)) {
  2313. if (!isMultiEdge) {
  2314. multiEdges[linkId] = 0;
  2315. }
  2316. var suffix = '@' + (++multiEdges[linkId]);
  2317. linkId = makeLinkId(fromId + suffix, toId + suffix);
  2318. }
  2319. return new Link(fromId, toId, data, linkId);
  2320. }
  2321. function getNodeCount() {
  2322. return nodes.size;
  2323. }
  2324. function getLinkCount() {
  2325. return links.length;
  2326. }
  2327. function getLinks(nodeId) {
  2328. var node = getNode(nodeId);
  2329. return node ? node.links : null;
  2330. }
  2331. function removeLink(link) {
  2332. if (!link) {
  2333. return false;
  2334. }
  2335. var idx = indexOfElementInArray(link, links);
  2336. if (idx < 0) {
  2337. return false;
  2338. }
  2339. enterModification();
  2340. links.splice(idx, 1);
  2341. var fromNode = getNode(link.fromId);
  2342. var toNode = getNode(link.toId);
  2343. if (fromNode) {
  2344. idx = indexOfElementInArray(link, fromNode.links);
  2345. if (idx >= 0) {
  2346. fromNode.links.splice(idx, 1);
  2347. }
  2348. }
  2349. if (toNode) {
  2350. idx = indexOfElementInArray(link, toNode.links);
  2351. if (idx >= 0) {
  2352. toNode.links.splice(idx, 1);
  2353. }
  2354. }
  2355. recordLinkChange(link, 'remove');
  2356. exitModification();
  2357. return true;
  2358. }
  2359. function getLink(fromNodeId, toNodeId) {
  2360. // TODO: Use sorted links to speed this up
  2361. var node = getNode(fromNodeId),
  2362. i;
  2363. if (!node || !node.links) {
  2364. return null;
  2365. }
  2366. for (i = 0; i < node.links.length; ++i) {
  2367. var link = node.links[i];
  2368. if (link.fromId === fromNodeId && link.toId === toNodeId) {
  2369. return link;
  2370. }
  2371. }
  2372. return null; // no link.
  2373. }
  2374. function clear() {
  2375. enterModification();
  2376. forEachNode(function(node) {
  2377. removeNode(node.id);
  2378. });
  2379. exitModification();
  2380. }
  2381. function forEachLink(callback) {
  2382. var i, length;
  2383. if (typeof callback === 'function') {
  2384. for (i = 0, length = links.length; i < length; ++i) {
  2385. callback(links[i]);
  2386. }
  2387. }
  2388. }
  2389. function forEachLinkedNode(nodeId, callback, oriented) {
  2390. var node = getNode(nodeId);
  2391. if (node && node.links && typeof callback === 'function') {
  2392. if (oriented) {
  2393. return forEachOrientedLink(node.links, nodeId, callback);
  2394. } else {
  2395. return forEachNonOrientedLink(node.links, nodeId, callback);
  2396. }
  2397. }
  2398. }
  2399. function forEachNonOrientedLink(links, nodeId, callback) {
  2400. var quitFast;
  2401. for (var i = 0; i < links.length; ++i) {
  2402. var link = links[i];
  2403. var linkedNodeId = link.fromId === nodeId ? link.toId : link.fromId;
  2404. quitFast = callback(nodes.get(linkedNodeId), link);
  2405. if (quitFast) {
  2406. return true; // Client does not need more iterations. Break now.
  2407. }
  2408. }
  2409. }
  2410. function forEachOrientedLink(links, nodeId, callback) {
  2411. var quitFast;
  2412. for (var i = 0; i < links.length; ++i) {
  2413. var link = links[i];
  2414. if (link.fromId === nodeId) {
  2415. quitFast = callback(nodes.get(link.toId), link);
  2416. if (quitFast) {
  2417. return true; // Client does not need more iterations. Break now.
  2418. }
  2419. }
  2420. }
  2421. }
  2422. // we will not fire anything until users of this library explicitly call `on()`
  2423. // method.
  2424. function noop() {}
  2425. // Enter, Exit modification allows bulk graph updates without firing events.
  2426. function enterModificationReal() {
  2427. suspendEvents += 1;
  2428. }
  2429. function exitModificationReal() {
  2430. suspendEvents -= 1;
  2431. if (suspendEvents === 0 && changes.length > 0) {
  2432. graphPart.fire('changed', changes);
  2433. changes.length = 0;
  2434. }
  2435. }
  2436. function forEachNode(callback) {
  2437. if (typeof callback !== 'function') {
  2438. throw new Error('Function is expected to iterate over graph nodes. You passed ' + callback);
  2439. }
  2440. var valuesIterator = nodes.values();
  2441. var nextValue = valuesIterator.next();
  2442. while (!nextValue.done) {
  2443. if (callback(nextValue.value)) {
  2444. return true; // client doesn't want to proceed. Return.
  2445. }
  2446. nextValue = valuesIterator.next();
  2447. }
  2448. }
  2449. }
  2450. // need this for old browsers. Should this be a separate module?
  2451. function indexOfElementInArray(element, array) {
  2452. if (!array) return -1;
  2453. if (array.indexOf) {
  2454. return array.indexOf(element);
  2455. }
  2456. var len = array.length,
  2457. i;
  2458. for (i = 0; i < len; i += 1) {
  2459. if (array[i] === element) {
  2460. return i;
  2461. }
  2462. }
  2463. return -1;
  2464. }
  2465. /**
  2466. * Internal structure to represent node;
  2467. */
  2468. function Node(id, data) {
  2469. this.id = id;
  2470. this.links = null;
  2471. this.data = data;
  2472. }
  2473. function addLinkToNode(node, link) {
  2474. if (node.links) {
  2475. node.links.push(link);
  2476. } else {
  2477. node.links = [link];
  2478. }
  2479. }
  2480. /**
  2481. * Internal structure to represent links;
  2482. */
  2483. function Link(fromId, toId, data, id) {
  2484. this.fromId = fromId;
  2485. this.toId = toId;
  2486. this.data = data;
  2487. this.id = id;
  2488. }
  2489. function makeLinkId(fromId, toId) {
  2490. return fromId.toString() + '👉 ' + toId.toString();
  2491. }
  2492. var ngraph_forcelayout = {exports: {}};
  2493. var generateCreateBody = {exports: {}};
  2494. var getVariableName$2 = function getVariableName(index) {
  2495. if (index === 0) return 'x';
  2496. if (index === 1) return 'y';
  2497. if (index === 2) return 'z';
  2498. return 'c' + (index + 1);
  2499. };
  2500. const getVariableName$1 = getVariableName$2;
  2501. var createPatternBuilder$6 = function createPatternBuilder(dimension) {
  2502. return pattern;
  2503. function pattern(template, config) {
  2504. let indent = (config && config.indent) || 0;
  2505. let join = (config && config.join !== undefined) ? config.join : '\n';
  2506. let indentString = Array(indent + 1).join(' ');
  2507. let buffer = [];
  2508. for (let i = 0; i < dimension; ++i) {
  2509. let variableName = getVariableName$1(i);
  2510. let prefix = (i === 0) ? '' : indentString;
  2511. buffer.push(prefix + template.replace(/{var}/g, variableName));
  2512. }
  2513. return buffer.join(join);
  2514. }
  2515. };
  2516. const createPatternBuilder$5 = createPatternBuilder$6;
  2517. generateCreateBody.exports = generateCreateBodyFunction$1;
  2518. generateCreateBody.exports.generateCreateBodyFunctionBody = generateCreateBodyFunctionBody;
  2519. // InlineTransform: getVectorCode
  2520. generateCreateBody.exports.getVectorCode = getVectorCode;
  2521. // InlineTransform: getBodyCode
  2522. generateCreateBody.exports.getBodyCode = getBodyCode;
  2523. // InlineTransformExport: module.exports = function() { return Body; }
  2524. function generateCreateBodyFunction$1(dimension, debugSetters) {
  2525. let code = generateCreateBodyFunctionBody(dimension, debugSetters);
  2526. let {Body} = (new Function(code))();
  2527. return Body;
  2528. }
  2529. function generateCreateBodyFunctionBody(dimension, debugSetters) {
  2530. let code = `
  2531. ${getVectorCode(dimension, debugSetters)}
  2532. ${getBodyCode(dimension)}
  2533. return {Body: Body, Vector: Vector};
  2534. `;
  2535. return code;
  2536. }
  2537. function getBodyCode(dimension) {
  2538. let pattern = createPatternBuilder$5(dimension);
  2539. let variableList = pattern('{var}', {join: ', '});
  2540. return `
  2541. function Body(${variableList}) {
  2542. this.isPinned = false;
  2543. this.pos = new Vector(${variableList});
  2544. this.force = new Vector();
  2545. this.velocity = new Vector();
  2546. this.mass = 1;
  2547. this.springCount = 0;
  2548. this.springLength = 0;
  2549. }
  2550. Body.prototype.reset = function() {
  2551. this.force.reset();
  2552. this.springCount = 0;
  2553. this.springLength = 0;
  2554. }
  2555. Body.prototype.setPosition = function (${variableList}) {
  2556. ${pattern('this.pos.{var} = {var} || 0;', {indent: 2})}
  2557. };`;
  2558. }
  2559. function getVectorCode(dimension, debugSetters) {
  2560. let pattern = createPatternBuilder$5(dimension);
  2561. let setters = '';
  2562. if (debugSetters) {
  2563. setters = `${pattern("\n\
  2564. var v{var};\n\
  2565. Object.defineProperty(this, '{var}', {\n\
  2566. set: function(v) { \n\
  2567. if (!Number.isFinite(v)) throw new Error('Cannot set non-numbers to {var}');\n\
  2568. v{var} = v; \n\
  2569. },\n\
  2570. get: function() { return v{var}; }\n\
  2571. });")}`;
  2572. }
  2573. let variableList = pattern('{var}', {join: ', '});
  2574. return `function Vector(${variableList}) {
  2575. ${setters}
  2576. if (typeof arguments[0] === 'object') {
  2577. // could be another vector
  2578. let v = arguments[0];
  2579. ${pattern('if (!Number.isFinite(v.{var})) throw new Error("Expected value is not a finite number at Vector constructor ({var})");', {indent: 4})}
  2580. ${pattern('this.{var} = v.{var};', {indent: 4})}
  2581. } else {
  2582. ${pattern('this.{var} = typeof {var} === "number" ? {var} : 0;', {indent: 4})}
  2583. }
  2584. }
  2585. Vector.prototype.reset = function () {
  2586. ${pattern('this.{var} = ', {join: ''})}0;
  2587. };`;
  2588. }
  2589. var generateQuadTree = {exports: {}};
  2590. const createPatternBuilder$4 = createPatternBuilder$6;
  2591. const getVariableName = getVariableName$2;
  2592. generateQuadTree.exports = generateQuadTreeFunction$1;
  2593. generateQuadTree.exports.generateQuadTreeFunctionBody = generateQuadTreeFunctionBody;
  2594. // These exports are for InlineTransform tool.
  2595. // InlineTransform: getInsertStackCode
  2596. generateQuadTree.exports.getInsertStackCode = getInsertStackCode;
  2597. // InlineTransform: getQuadNodeCode
  2598. generateQuadTree.exports.getQuadNodeCode = getQuadNodeCode;
  2599. // InlineTransform: isSamePosition
  2600. generateQuadTree.exports.isSamePosition = isSamePosition;
  2601. // InlineTransform: getChildBodyCode
  2602. generateQuadTree.exports.getChildBodyCode = getChildBodyCode;
  2603. // InlineTransform: setChildBodyCode
  2604. generateQuadTree.exports.setChildBodyCode = setChildBodyCode;
  2605. function generateQuadTreeFunction$1(dimension) {
  2606. let code = generateQuadTreeFunctionBody(dimension);
  2607. return (new Function(code))();
  2608. }
  2609. function generateQuadTreeFunctionBody(dimension) {
  2610. let pattern = createPatternBuilder$4(dimension);
  2611. let quadCount = Math.pow(2, dimension);
  2612. let code = `
  2613. ${getInsertStackCode()}
  2614. ${getQuadNodeCode(dimension)}
  2615. ${isSamePosition(dimension)}
  2616. ${getChildBodyCode(dimension)}
  2617. ${setChildBodyCode(dimension)}
  2618. function createQuadTree(options, random) {
  2619. options = options || {};
  2620. options.gravity = typeof options.gravity === 'number' ? options.gravity : -1;
  2621. options.theta = typeof options.theta === 'number' ? options.theta : 0.8;
  2622. var gravity = options.gravity;
  2623. var updateQueue = [];
  2624. var insertStack = new InsertStack();
  2625. var theta = options.theta;
  2626. var nodesCache = [];
  2627. var currentInCache = 0;
  2628. var root = newNode();
  2629. return {
  2630. insertBodies: insertBodies,
  2631. /**
  2632. * Gets root node if it is present
  2633. */
  2634. getRoot: function() {
  2635. return root;
  2636. },
  2637. updateBodyForce: update,
  2638. options: function(newOptions) {
  2639. if (newOptions) {
  2640. if (typeof newOptions.gravity === 'number') {
  2641. gravity = newOptions.gravity;
  2642. }
  2643. if (typeof newOptions.theta === 'number') {
  2644. theta = newOptions.theta;
  2645. }
  2646. return this;
  2647. }
  2648. return {
  2649. gravity: gravity,
  2650. theta: theta
  2651. };
  2652. }
  2653. };
  2654. function newNode() {
  2655. // To avoid pressure on GC we reuse nodes.
  2656. var node = nodesCache[currentInCache];
  2657. if (node) {
  2658. ${assignQuads(' node.')}
  2659. node.body = null;
  2660. node.mass = ${pattern('node.mass_{var} = ', {join: ''})}0;
  2661. ${pattern('node.min_{var} = node.max_{var} = ', {join: ''})}0;
  2662. } else {
  2663. node = new QuadNode();
  2664. nodesCache[currentInCache] = node;
  2665. }
  2666. ++currentInCache;
  2667. return node;
  2668. }
  2669. function update(sourceBody) {
  2670. var queue = updateQueue;
  2671. var v;
  2672. ${pattern('var d{var};', {indent: 4})}
  2673. var r;
  2674. ${pattern('var f{var} = 0;', {indent: 4})}
  2675. var queueLength = 1;
  2676. var shiftIdx = 0;
  2677. var pushIdx = 1;
  2678. queue[0] = root;
  2679. while (queueLength) {
  2680. var node = queue[shiftIdx];
  2681. var body = node.body;
  2682. queueLength -= 1;
  2683. shiftIdx += 1;
  2684. var differentBody = (body !== sourceBody);
  2685. if (body && differentBody) {
  2686. // If the current node is a leaf node (and it is not source body),
  2687. // calculate the force exerted by the current node on body, and add this
  2688. // amount to body's net force.
  2689. ${pattern('d{var} = body.pos.{var} - sourceBody.pos.{var};', {indent: 8})}
  2690. r = Math.sqrt(${pattern('d{var} * d{var}', {join: ' + '})});
  2691. if (r === 0) {
  2692. // Poor man's protection against zero distance.
  2693. ${pattern('d{var} = (random.nextDouble() - 0.5) / 50;', {indent: 10})}
  2694. r = Math.sqrt(${pattern('d{var} * d{var}', {join: ' + '})});
  2695. }
  2696. // This is standard gravitation force calculation but we divide
  2697. // by r^3 to save two operations when normalizing force vector.
  2698. v = gravity * body.mass * sourceBody.mass / (r * r * r);
  2699. ${pattern('f{var} += v * d{var};', {indent: 8})}
  2700. } else if (differentBody) {
  2701. // Otherwise, calculate the ratio s / r, where s is the width of the region
  2702. // represented by the internal node, and r is the distance between the body
  2703. // and the node's center-of-mass
  2704. ${pattern('d{var} = node.mass_{var} / node.mass - sourceBody.pos.{var};', {indent: 8})}
  2705. r = Math.sqrt(${pattern('d{var} * d{var}', {join: ' + '})});
  2706. if (r === 0) {
  2707. // Sorry about code duplication. I don't want to create many functions
  2708. // right away. Just want to see performance first.
  2709. ${pattern('d{var} = (random.nextDouble() - 0.5) / 50;', {indent: 10})}
  2710. r = Math.sqrt(${pattern('d{var} * d{var}', {join: ' + '})});
  2711. }
  2712. // If s / r < θ, treat this internal node as a single body, and calculate the
  2713. // force it exerts on sourceBody, and add this amount to sourceBody's net force.
  2714. if ((node.max_${getVariableName(0)} - node.min_${getVariableName(0)}) / r < theta) {
  2715. // in the if statement above we consider node's width only
  2716. // because the region was made into square during tree creation.
  2717. // Thus there is no difference between using width or height.
  2718. v = gravity * node.mass * sourceBody.mass / (r * r * r);
  2719. ${pattern('f{var} += v * d{var};', {indent: 10})}
  2720. } else {
  2721. // Otherwise, run the procedure recursively on each of the current node's children.
  2722. // I intentionally unfolded this loop, to save several CPU cycles.
  2723. ${runRecursiveOnChildren()}
  2724. }
  2725. }
  2726. }
  2727. ${pattern('sourceBody.force.{var} += f{var};', {indent: 4})}
  2728. }
  2729. function insertBodies(bodies) {
  2730. ${pattern('var {var}min = Number.MAX_VALUE;', {indent: 4})}
  2731. ${pattern('var {var}max = Number.MIN_VALUE;', {indent: 4})}
  2732. var i = bodies.length;
  2733. // To reduce quad tree depth we are looking for exact bounding box of all particles.
  2734. while (i--) {
  2735. var pos = bodies[i].pos;
  2736. ${pattern('if (pos.{var} < {var}min) {var}min = pos.{var};', {indent: 6})}
  2737. ${pattern('if (pos.{var} > {var}max) {var}max = pos.{var};', {indent: 6})}
  2738. }
  2739. // Makes the bounds square.
  2740. var maxSideLength = -Infinity;
  2741. ${pattern('if ({var}max - {var}min > maxSideLength) maxSideLength = {var}max - {var}min ;', {indent: 4})}
  2742. currentInCache = 0;
  2743. root = newNode();
  2744. ${pattern('root.min_{var} = {var}min;', {indent: 4})}
  2745. ${pattern('root.max_{var} = {var}min + maxSideLength;', {indent: 4})}
  2746. i = bodies.length - 1;
  2747. if (i >= 0) {
  2748. root.body = bodies[i];
  2749. }
  2750. while (i--) {
  2751. insert(bodies[i], root);
  2752. }
  2753. }
  2754. function insert(newBody) {
  2755. insertStack.reset();
  2756. insertStack.push(root, newBody);
  2757. while (!insertStack.isEmpty()) {
  2758. var stackItem = insertStack.pop();
  2759. var node = stackItem.node;
  2760. var body = stackItem.body;
  2761. if (!node.body) {
  2762. // This is internal node. Update the total mass of the node and center-of-mass.
  2763. ${pattern('var {var} = body.pos.{var};', {indent: 8})}
  2764. node.mass += body.mass;
  2765. ${pattern('node.mass_{var} += body.mass * {var};', {indent: 8})}
  2766. // Recursively insert the body in the appropriate quadrant.
  2767. // But first find the appropriate quadrant.
  2768. var quadIdx = 0; // Assume we are in the 0's quad.
  2769. ${pattern('var min_{var} = node.min_{var};', {indent: 8})}
  2770. ${pattern('var max_{var} = (min_{var} + node.max_{var}) / 2;', {indent: 8})}
  2771. ${assignInsertionQuadIndex(8)}
  2772. var child = getChild(node, quadIdx);
  2773. if (!child) {
  2774. // The node is internal but this quadrant is not taken. Add
  2775. // subnode to it.
  2776. child = newNode();
  2777. ${pattern('child.min_{var} = min_{var};', {indent: 10})}
  2778. ${pattern('child.max_{var} = max_{var};', {indent: 10})}
  2779. child.body = body;
  2780. setChild(node, quadIdx, child);
  2781. } else {
  2782. // continue searching in this quadrant.
  2783. insertStack.push(child, body);
  2784. }
  2785. } else {
  2786. // We are trying to add to the leaf node.
  2787. // We have to convert current leaf into internal node
  2788. // and continue adding two nodes.
  2789. var oldBody = node.body;
  2790. node.body = null; // internal nodes do not cary bodies
  2791. if (isSamePosition(oldBody.pos, body.pos)) {
  2792. // Prevent infinite subdivision by bumping one node
  2793. // anywhere in this quadrant
  2794. var retriesCount = 3;
  2795. do {
  2796. var offset = random.nextDouble();
  2797. ${pattern('var d{var} = (node.max_{var} - node.min_{var}) * offset;', {indent: 12})}
  2798. ${pattern('oldBody.pos.{var} = node.min_{var} + d{var};', {indent: 12})}
  2799. retriesCount -= 1;
  2800. // Make sure we don't bump it out of the box. If we do, next iteration should fix it
  2801. } while (retriesCount > 0 && isSamePosition(oldBody.pos, body.pos));
  2802. if (retriesCount === 0 && isSamePosition(oldBody.pos, body.pos)) {
  2803. // This is very bad, we ran out of precision.
  2804. // if we do not return from the method we'll get into
  2805. // infinite loop here. So we sacrifice correctness of layout, and keep the app running
  2806. // Next layout iteration should get larger bounding box in the first step and fix this
  2807. return;
  2808. }
  2809. }
  2810. // Next iteration should subdivide node further.
  2811. insertStack.push(node, oldBody);
  2812. insertStack.push(node, body);
  2813. }
  2814. }
  2815. }
  2816. }
  2817. return createQuadTree;
  2818. `;
  2819. return code;
  2820. function assignInsertionQuadIndex(indentCount) {
  2821. let insertionCode = [];
  2822. let indent = Array(indentCount + 1).join(' ');
  2823. for (let i = 0; i < dimension; ++i) {
  2824. insertionCode.push(indent + `if (${getVariableName(i)} > max_${getVariableName(i)}) {`);
  2825. insertionCode.push(indent + ` quadIdx = quadIdx + ${Math.pow(2, i)};`);
  2826. insertionCode.push(indent + ` min_${getVariableName(i)} = max_${getVariableName(i)};`);
  2827. insertionCode.push(indent + ` max_${getVariableName(i)} = node.max_${getVariableName(i)};`);
  2828. insertionCode.push(indent + `}`);
  2829. }
  2830. return insertionCode.join('\n');
  2831. // if (x > max_x) { // somewhere in the eastern part.
  2832. // quadIdx = quadIdx + 1;
  2833. // left = right;
  2834. // right = node.right;
  2835. // }
  2836. }
  2837. function runRecursiveOnChildren() {
  2838. let indent = Array(11).join(' ');
  2839. let recursiveCode = [];
  2840. for (let i = 0; i < quadCount; ++i) {
  2841. recursiveCode.push(indent + `if (node.quad${i}) {`);
  2842. recursiveCode.push(indent + ` queue[pushIdx] = node.quad${i};`);
  2843. recursiveCode.push(indent + ` queueLength += 1;`);
  2844. recursiveCode.push(indent + ` pushIdx += 1;`);
  2845. recursiveCode.push(indent + `}`);
  2846. }
  2847. return recursiveCode.join('\n');
  2848. // if (node.quad0) {
  2849. // queue[pushIdx] = node.quad0;
  2850. // queueLength += 1;
  2851. // pushIdx += 1;
  2852. // }
  2853. }
  2854. function assignQuads(indent) {
  2855. // this.quad0 = null;
  2856. // this.quad1 = null;
  2857. // this.quad2 = null;
  2858. // this.quad3 = null;
  2859. let quads = [];
  2860. for (let i = 0; i < quadCount; ++i) {
  2861. quads.push(`${indent}quad${i} = null;`);
  2862. }
  2863. return quads.join('\n');
  2864. }
  2865. }
  2866. function isSamePosition(dimension) {
  2867. let pattern = createPatternBuilder$4(dimension);
  2868. return `
  2869. function isSamePosition(point1, point2) {
  2870. ${pattern('var d{var} = Math.abs(point1.{var} - point2.{var});', {indent: 2})}
  2871. return ${pattern('d{var} < 1e-8', {join: ' && '})};
  2872. }
  2873. `;
  2874. }
  2875. function setChildBodyCode(dimension) {
  2876. var quadCount = Math.pow(2, dimension);
  2877. return `
  2878. function setChild(node, idx, child) {
  2879. ${setChildBody()}
  2880. }`;
  2881. function setChildBody() {
  2882. let childBody = [];
  2883. for (let i = 0; i < quadCount; ++i) {
  2884. let prefix = (i === 0) ? ' ' : ' else ';
  2885. childBody.push(`${prefix}if (idx === ${i}) node.quad${i} = child;`);
  2886. }
  2887. return childBody.join('\n');
  2888. // if (idx === 0) node.quad0 = child;
  2889. // else if (idx === 1) node.quad1 = child;
  2890. // else if (idx === 2) node.quad2 = child;
  2891. // else if (idx === 3) node.quad3 = child;
  2892. }
  2893. }
  2894. function getChildBodyCode(dimension) {
  2895. return `function getChild(node, idx) {
  2896. ${getChildBody()}
  2897. return null;
  2898. }`;
  2899. function getChildBody() {
  2900. let childBody = [];
  2901. let quadCount = Math.pow(2, dimension);
  2902. for (let i = 0; i < quadCount; ++i) {
  2903. childBody.push(` if (idx === ${i}) return node.quad${i};`);
  2904. }
  2905. return childBody.join('\n');
  2906. // if (idx === 0) return node.quad0;
  2907. // if (idx === 1) return node.quad1;
  2908. // if (idx === 2) return node.quad2;
  2909. // if (idx === 3) return node.quad3;
  2910. }
  2911. }
  2912. function getQuadNodeCode(dimension) {
  2913. let pattern = createPatternBuilder$4(dimension);
  2914. let quadCount = Math.pow(2, dimension);
  2915. var quadNodeCode = `
  2916. function QuadNode() {
  2917. // body stored inside this node. In quad tree only leaf nodes (by construction)
  2918. // contain bodies:
  2919. this.body = null;
  2920. // Child nodes are stored in quads. Each quad is presented by number:
  2921. // 0 | 1
  2922. // -----
  2923. // 2 | 3
  2924. ${assignQuads(' this.')}
  2925. // Total mass of current node
  2926. this.mass = 0;
  2927. // Center of mass coordinates
  2928. ${pattern('this.mass_{var} = 0;', {indent: 2})}
  2929. // bounding box coordinates
  2930. ${pattern('this.min_{var} = 0;', {indent: 2})}
  2931. ${pattern('this.max_{var} = 0;', {indent: 2})}
  2932. }
  2933. `;
  2934. return quadNodeCode;
  2935. function assignQuads(indent) {
  2936. // this.quad0 = null;
  2937. // this.quad1 = null;
  2938. // this.quad2 = null;
  2939. // this.quad3 = null;
  2940. let quads = [];
  2941. for (let i = 0; i < quadCount; ++i) {
  2942. quads.push(`${indent}quad${i} = null;`);
  2943. }
  2944. return quads.join('\n');
  2945. }
  2946. }
  2947. function getInsertStackCode() {
  2948. return `
  2949. /**
  2950. * Our implementation of QuadTree is non-recursive to avoid GC hit
  2951. * This data structure represent stack of elements
  2952. * which we are trying to insert into quad tree.
  2953. */
  2954. function InsertStack () {
  2955. this.stack = [];
  2956. this.popIdx = 0;
  2957. }
  2958. InsertStack.prototype = {
  2959. isEmpty: function() {
  2960. return this.popIdx === 0;
  2961. },
  2962. push: function (node, body) {
  2963. var item = this.stack[this.popIdx];
  2964. if (!item) {
  2965. // we are trying to avoid memory pressure: create new element
  2966. // only when absolutely necessary
  2967. this.stack[this.popIdx] = new InsertStackElement(node, body);
  2968. } else {
  2969. item.node = node;
  2970. item.body = body;
  2971. }
  2972. ++this.popIdx;
  2973. },
  2974. pop: function () {
  2975. if (this.popIdx > 0) {
  2976. return this.stack[--this.popIdx];
  2977. }
  2978. },
  2979. reset: function () {
  2980. this.popIdx = 0;
  2981. }
  2982. };
  2983. function InsertStackElement(node, body) {
  2984. this.node = node; // QuadTree node
  2985. this.body = body; // physical body which needs to be inserted to node
  2986. }
  2987. `;
  2988. }
  2989. var generateBounds = {exports: {}};
  2990. generateBounds.exports = generateBoundsFunction$1;
  2991. generateBounds.exports.generateFunctionBody = generateBoundsFunctionBody;
  2992. const createPatternBuilder$3 = createPatternBuilder$6;
  2993. function generateBoundsFunction$1(dimension) {
  2994. let code = generateBoundsFunctionBody(dimension);
  2995. return new Function('bodies', 'settings', 'random', code);
  2996. }
  2997. function generateBoundsFunctionBody(dimension) {
  2998. let pattern = createPatternBuilder$3(dimension);
  2999. let code = `
  3000. var boundingBox = {
  3001. ${pattern('min_{var}: 0, max_{var}: 0,', {indent: 4})}
  3002. };
  3003. return {
  3004. box: boundingBox,
  3005. update: updateBoundingBox,
  3006. reset: resetBoundingBox,
  3007. getBestNewPosition: function (neighbors) {
  3008. var ${pattern('base_{var} = 0', {join: ', '})};
  3009. if (neighbors.length) {
  3010. for (var i = 0; i < neighbors.length; ++i) {
  3011. let neighborPos = neighbors[i].pos;
  3012. ${pattern('base_{var} += neighborPos.{var};', {indent: 10})}
  3013. }
  3014. ${pattern('base_{var} /= neighbors.length;', {indent: 8})}
  3015. } else {
  3016. ${pattern('base_{var} = (boundingBox.min_{var} + boundingBox.max_{var}) / 2;', {indent: 8})}
  3017. }
  3018. var springLength = settings.springLength;
  3019. return {
  3020. ${pattern('{var}: base_{var} + (random.nextDouble() - 0.5) * springLength,', {indent: 8})}
  3021. };
  3022. }
  3023. };
  3024. function updateBoundingBox() {
  3025. var i = bodies.length;
  3026. if (i === 0) return; // No bodies - no borders.
  3027. ${pattern('var max_{var} = -Infinity;', {indent: 4})}
  3028. ${pattern('var min_{var} = Infinity;', {indent: 4})}
  3029. while(i--) {
  3030. // this is O(n), it could be done faster with quadtree, if we check the root node bounds
  3031. var bodyPos = bodies[i].pos;
  3032. ${pattern('if (bodyPos.{var} < min_{var}) min_{var} = bodyPos.{var};', {indent: 6})}
  3033. ${pattern('if (bodyPos.{var} > max_{var}) max_{var} = bodyPos.{var};', {indent: 6})}
  3034. }
  3035. ${pattern('boundingBox.min_{var} = min_{var};', {indent: 4})}
  3036. ${pattern('boundingBox.max_{var} = max_{var};', {indent: 4})}
  3037. }
  3038. function resetBoundingBox() {
  3039. ${pattern('boundingBox.min_{var} = boundingBox.max_{var} = 0;', {indent: 4})}
  3040. }
  3041. `;
  3042. return code;
  3043. }
  3044. var generateCreateDragForce = {exports: {}};
  3045. const createPatternBuilder$2 = createPatternBuilder$6;
  3046. generateCreateDragForce.exports = generateCreateDragForceFunction$1;
  3047. generateCreateDragForce.exports.generateCreateDragForceFunctionBody = generateCreateDragForceFunctionBody;
  3048. function generateCreateDragForceFunction$1(dimension) {
  3049. let code = generateCreateDragForceFunctionBody(dimension);
  3050. return new Function('options', code);
  3051. }
  3052. function generateCreateDragForceFunctionBody(dimension) {
  3053. let pattern = createPatternBuilder$2(dimension);
  3054. let code = `
  3055. if (!Number.isFinite(options.dragCoefficient)) throw new Error('dragCoefficient is not a finite number');
  3056. return {
  3057. update: function(body) {
  3058. ${pattern('body.force.{var} -= options.dragCoefficient * body.velocity.{var};', {indent: 6})}
  3059. }
  3060. };
  3061. `;
  3062. return code;
  3063. }
  3064. var generateCreateSpringForce = {exports: {}};
  3065. const createPatternBuilder$1 = createPatternBuilder$6;
  3066. generateCreateSpringForce.exports = generateCreateSpringForceFunction$1;
  3067. generateCreateSpringForce.exports.generateCreateSpringForceFunctionBody = generateCreateSpringForceFunctionBody;
  3068. function generateCreateSpringForceFunction$1(dimension) {
  3069. let code = generateCreateSpringForceFunctionBody(dimension);
  3070. return new Function('options', 'random', code);
  3071. }
  3072. function generateCreateSpringForceFunctionBody(dimension) {
  3073. let pattern = createPatternBuilder$1(dimension);
  3074. let code = `
  3075. if (!Number.isFinite(options.springCoefficient)) throw new Error('Spring coefficient is not a number');
  3076. if (!Number.isFinite(options.springLength)) throw new Error('Spring length is not a number');
  3077. return {
  3078. /**
  3079. * Updates forces acting on a spring
  3080. */
  3081. update: function (spring) {
  3082. var body1 = spring.from;
  3083. var body2 = spring.to;
  3084. var length = spring.length < 0 ? options.springLength : spring.length;
  3085. ${pattern('var d{var} = body2.pos.{var} - body1.pos.{var};', {indent: 6})}
  3086. var r = Math.sqrt(${pattern('d{var} * d{var}', {join: ' + '})});
  3087. if (r === 0) {
  3088. ${pattern('d{var} = (random.nextDouble() - 0.5) / 50;', {indent: 8})}
  3089. r = Math.sqrt(${pattern('d{var} * d{var}', {join: ' + '})});
  3090. }
  3091. var d = r - length;
  3092. var coefficient = ((spring.coefficient > 0) ? spring.coefficient : options.springCoefficient) * d / r;
  3093. ${pattern('body1.force.{var} += coefficient * d{var}', {indent: 6})};
  3094. body1.springCount += 1;
  3095. body1.springLength += r;
  3096. ${pattern('body2.force.{var} -= coefficient * d{var}', {indent: 6})};
  3097. body2.springCount += 1;
  3098. body2.springLength += r;
  3099. }
  3100. };
  3101. `;
  3102. return code;
  3103. }
  3104. var generateIntegrator = {exports: {}};
  3105. const createPatternBuilder = createPatternBuilder$6;
  3106. generateIntegrator.exports = generateIntegratorFunction$1;
  3107. generateIntegrator.exports.generateIntegratorFunctionBody = generateIntegratorFunctionBody;
  3108. function generateIntegratorFunction$1(dimension) {
  3109. let code = generateIntegratorFunctionBody(dimension);
  3110. return new Function('bodies', 'timeStep', 'adaptiveTimeStepWeight', code);
  3111. }
  3112. function generateIntegratorFunctionBody(dimension) {
  3113. let pattern = createPatternBuilder(dimension);
  3114. let code = `
  3115. var length = bodies.length;
  3116. if (length === 0) return 0;
  3117. ${pattern('var d{var} = 0, t{var} = 0;', {indent: 2})}
  3118. for (var i = 0; i < length; ++i) {
  3119. var body = bodies[i];
  3120. if (body.isPinned) continue;
  3121. if (adaptiveTimeStepWeight && body.springCount) {
  3122. timeStep = (adaptiveTimeStepWeight * body.springLength/body.springCount);
  3123. }
  3124. var coeff = timeStep / body.mass;
  3125. ${pattern('body.velocity.{var} += coeff * body.force.{var};', {indent: 4})}
  3126. ${pattern('var v{var} = body.velocity.{var};', {indent: 4})}
  3127. var v = Math.sqrt(${pattern('v{var} * v{var}', {join: ' + '})});
  3128. if (v > 1) {
  3129. // We normalize it so that we move within timeStep range.
  3130. // for the case when v <= 1 - we let velocity to fade out.
  3131. ${pattern('body.velocity.{var} = v{var} / v;', {indent: 6})}
  3132. }
  3133. ${pattern('d{var} = timeStep * body.velocity.{var};', {indent: 4})}
  3134. ${pattern('body.pos.{var} += d{var};', {indent: 4})}
  3135. ${pattern('t{var} += Math.abs(d{var});', {indent: 4})}
  3136. }
  3137. return (${pattern('t{var} * t{var}', {join: ' + '})})/length;
  3138. `;
  3139. return code;
  3140. }
  3141. var spring = Spring;
  3142. /**
  3143. * Represents a physical spring. Spring connects two bodies, has rest length
  3144. * stiffness coefficient and optional weight
  3145. */
  3146. function Spring(fromBody, toBody, length, springCoefficient) {
  3147. this.from = fromBody;
  3148. this.to = toBody;
  3149. this.length = length;
  3150. this.coefficient = springCoefficient;
  3151. }
  3152. var ngraph_merge = merge;
  3153. /**
  3154. * Augments `target` with properties in `options`. Does not override
  3155. * target's properties if they are defined and matches expected type in
  3156. * options
  3157. *
  3158. * @returns {Object} merged object
  3159. */
  3160. function merge(target, options) {
  3161. var key;
  3162. if (!target) { target = {}; }
  3163. if (options) {
  3164. for (key in options) {
  3165. if (options.hasOwnProperty(key)) {
  3166. var targetHasIt = target.hasOwnProperty(key),
  3167. optionsValueType = typeof options[key],
  3168. shouldReplace = !targetHasIt || (typeof target[key] !== optionsValueType);
  3169. if (shouldReplace) {
  3170. target[key] = options[key];
  3171. } else if (optionsValueType === 'object') {
  3172. // go deep, don't care about loops here, we are simple API!:
  3173. target[key] = merge(target[key], options[key]);
  3174. }
  3175. }
  3176. }
  3177. }
  3178. return target;
  3179. }
  3180. var ngraph_random = {exports: {}};
  3181. ngraph_random.exports = random;
  3182. // TODO: Deprecate?
  3183. ngraph_random.exports.random = random,
  3184. ngraph_random.exports.randomIterator = randomIterator;
  3185. /**
  3186. * Creates seeded PRNG with two methods:
  3187. * next() and nextDouble()
  3188. */
  3189. function random(inputSeed) {
  3190. var seed = typeof inputSeed === 'number' ? inputSeed : (+new Date());
  3191. return new Generator(seed)
  3192. }
  3193. function Generator(seed) {
  3194. this.seed = seed;
  3195. }
  3196. /**
  3197. * Generates random integer number in the range from 0 (inclusive) to maxValue (exclusive)
  3198. *
  3199. * @param maxValue Number REQUIRED. Omitting this number will result in NaN values from PRNG.
  3200. */
  3201. Generator.prototype.next = next;
  3202. /**
  3203. * Generates random double number in the range from 0 (inclusive) to 1 (exclusive)
  3204. * This function is the same as Math.random() (except that it could be seeded)
  3205. */
  3206. Generator.prototype.nextDouble = nextDouble;
  3207. /**
  3208. * Returns a random real number from uniform distribution in [0, 1)
  3209. */
  3210. Generator.prototype.uniform = nextDouble;
  3211. /**
  3212. * Returns a random real number from a Gaussian distribution
  3213. * with 0 as a mean, and 1 as standard deviation u ~ N(0,1)
  3214. */
  3215. Generator.prototype.gaussian = gaussian;
  3216. function gaussian() {
  3217. // use the polar form of the Box-Muller transform
  3218. // based on https://introcs.cs.princeton.edu/java/23recursion/StdRandom.java
  3219. var r, x, y;
  3220. do {
  3221. x = this.nextDouble() * 2 - 1;
  3222. y = this.nextDouble() * 2 - 1;
  3223. r = x * x + y * y;
  3224. } while (r >= 1 || r === 0);
  3225. return x * Math.sqrt(-2 * Math.log(r)/r);
  3226. }
  3227. /**
  3228. * See https://twitter.com/anvaka/status/1296182534150135808
  3229. */
  3230. Generator.prototype.levy = levy;
  3231. function levy() {
  3232. var beta = 3 / 2;
  3233. var sigma = Math.pow(
  3234. gamma( 1 + beta ) * Math.sin(Math.PI * beta / 2) /
  3235. (gamma((1 + beta) / 2) * beta * Math.pow(2, (beta - 1) / 2)),
  3236. 1/beta
  3237. );
  3238. return this.gaussian() * sigma / Math.pow(Math.abs(this.gaussian()), 1/beta);
  3239. }
  3240. // gamma function approximation
  3241. function gamma(z) {
  3242. return Math.sqrt(2 * Math.PI / z) * Math.pow((1 / Math.E) * (z + 1 / (12 * z - 1 / (10 * z))), z);
  3243. }
  3244. function nextDouble() {
  3245. var seed = this.seed;
  3246. // Robert Jenkins' 32 bit integer hash function.
  3247. seed = ((seed + 0x7ed55d16) + (seed << 12)) & 0xffffffff;
  3248. seed = ((seed ^ 0xc761c23c) ^ (seed >>> 19)) & 0xffffffff;
  3249. seed = ((seed + 0x165667b1) + (seed << 5)) & 0xffffffff;
  3250. seed = ((seed + 0xd3a2646c) ^ (seed << 9)) & 0xffffffff;
  3251. seed = ((seed + 0xfd7046c5) + (seed << 3)) & 0xffffffff;
  3252. seed = ((seed ^ 0xb55a4f09) ^ (seed >>> 16)) & 0xffffffff;
  3253. this.seed = seed;
  3254. return (seed & 0xfffffff) / 0x10000000;
  3255. }
  3256. function next(maxValue) {
  3257. return Math.floor(this.nextDouble() * maxValue);
  3258. }
  3259. /*
  3260. * Creates iterator over array, which returns items of array in random order
  3261. * Time complexity is guaranteed to be O(n);
  3262. */
  3263. function randomIterator(array, customRandom) {
  3264. var localRandom = customRandom || random();
  3265. if (typeof localRandom.next !== 'function') {
  3266. throw new Error('customRandom does not match expected API: next() function is missing');
  3267. }
  3268. return {
  3269. forEach: forEach,
  3270. /**
  3271. * Shuffles array randomly, in place.
  3272. */
  3273. shuffle: shuffle
  3274. };
  3275. function shuffle() {
  3276. var i, j, t;
  3277. for (i = array.length - 1; i > 0; --i) {
  3278. j = localRandom.next(i + 1); // i inclusive
  3279. t = array[j];
  3280. array[j] = array[i];
  3281. array[i] = t;
  3282. }
  3283. return array;
  3284. }
  3285. function forEach(callback) {
  3286. var i, j, t;
  3287. for (i = array.length - 1; i > 0; --i) {
  3288. j = localRandom.next(i + 1); // i inclusive
  3289. t = array[j];
  3290. array[j] = array[i];
  3291. array[i] = t;
  3292. callback(t);
  3293. }
  3294. if (array.length) {
  3295. callback(array[0]);
  3296. }
  3297. }
  3298. }
  3299. /**
  3300. * Manages a simulation of physical forces acting on bodies and springs.
  3301. */
  3302. var createPhysicsSimulator_1 = createPhysicsSimulator;
  3303. var generateCreateBodyFunction = generateCreateBody.exports;
  3304. var generateQuadTreeFunction = generateQuadTree.exports;
  3305. var generateBoundsFunction = generateBounds.exports;
  3306. var generateCreateDragForceFunction = generateCreateDragForce.exports;
  3307. var generateCreateSpringForceFunction = generateCreateSpringForce.exports;
  3308. var generateIntegratorFunction = generateIntegrator.exports;
  3309. var dimensionalCache = {};
  3310. function createPhysicsSimulator(settings) {
  3311. var Spring = spring;
  3312. var merge = ngraph_merge;
  3313. var eventify = ngraph_events;
  3314. if (settings) {
  3315. // Check for names from older versions of the layout
  3316. if (settings.springCoeff !== undefined) throw new Error('springCoeff was renamed to springCoefficient');
  3317. if (settings.dragCoeff !== undefined) throw new Error('dragCoeff was renamed to dragCoefficient');
  3318. }
  3319. settings = merge(settings, {
  3320. /**
  3321. * Ideal length for links (springs in physical model).
  3322. */
  3323. springLength: 10,
  3324. /**
  3325. * Hook's law coefficient. 1 - solid spring.
  3326. */
  3327. springCoefficient: 0.8,
  3328. /**
  3329. * Coulomb's law coefficient. It's used to repel nodes thus should be negative
  3330. * if you make it positive nodes start attract each other :).
  3331. */
  3332. gravity: -12,
  3333. /**
  3334. * Theta coefficient from Barnes Hut simulation. Ranged between (0, 1).
  3335. * The closer it's to 1 the more nodes algorithm will have to go through.
  3336. * Setting it to one makes Barnes Hut simulation no different from
  3337. * brute-force forces calculation (each node is considered).
  3338. */
  3339. theta: 0.8,
  3340. /**
  3341. * Drag force coefficient. Used to slow down system, thus should be less than 1.
  3342. * The closer it is to 0 the less tight system will be.
  3343. */
  3344. dragCoefficient: 0.9, // TODO: Need to rename this to something better. E.g. `dragCoefficient`
  3345. /**
  3346. * Default time step (dt) for forces integration
  3347. */
  3348. timeStep : 0.5,
  3349. /**
  3350. * Adaptive time step uses average spring length to compute actual time step:
  3351. * See: https://twitter.com/anvaka/status/1293067160755957760
  3352. */
  3353. adaptiveTimeStepWeight: 0,
  3354. /**
  3355. * This parameter defines number of dimensions of the space where simulation
  3356. * is performed.
  3357. */
  3358. dimensions: 2,
  3359. /**
  3360. * In debug mode more checks are performed, this will help you catch errors
  3361. * quickly, however for production build it is recommended to turn off this flag
  3362. * to speed up computation.
  3363. */
  3364. debug: false
  3365. });
  3366. var factory = dimensionalCache[settings.dimensions];
  3367. if (!factory) {
  3368. var dimensions = settings.dimensions;
  3369. factory = {
  3370. Body: generateCreateBodyFunction(dimensions, settings.debug),
  3371. createQuadTree: generateQuadTreeFunction(dimensions),
  3372. createBounds: generateBoundsFunction(dimensions),
  3373. createDragForce: generateCreateDragForceFunction(dimensions),
  3374. createSpringForce: generateCreateSpringForceFunction(dimensions),
  3375. integrate: generateIntegratorFunction(dimensions),
  3376. };
  3377. dimensionalCache[dimensions] = factory;
  3378. }
  3379. var Body = factory.Body;
  3380. var createQuadTree = factory.createQuadTree;
  3381. var createBounds = factory.createBounds;
  3382. var createDragForce = factory.createDragForce;
  3383. var createSpringForce = factory.createSpringForce;
  3384. var integrate = factory.integrate;
  3385. var createBody = pos => new Body(pos);
  3386. var random = ngraph_random.exports.random(42);
  3387. var bodies = []; // Bodies in this simulation.
  3388. var springs = []; // Springs in this simulation.
  3389. var quadTree = createQuadTree(settings, random);
  3390. var bounds = createBounds(bodies, settings, random);
  3391. var springForce = createSpringForce(settings, random);
  3392. var dragForce = createDragForce(settings);
  3393. var totalMovement = 0; // how much movement we made on last step
  3394. var forces = [];
  3395. var forceMap = new Map();
  3396. var iterationNumber = 0;
  3397. addForce('nbody', nbodyForce);
  3398. addForce('spring', updateSpringForce);
  3399. var publicApi = {
  3400. /**
  3401. * Array of bodies, registered with current simulator
  3402. *
  3403. * Note: To add new body, use addBody() method. This property is only
  3404. * exposed for testing/performance purposes.
  3405. */
  3406. bodies: bodies,
  3407. quadTree: quadTree,
  3408. /**
  3409. * Array of springs, registered with current simulator
  3410. *
  3411. * Note: To add new spring, use addSpring() method. This property is only
  3412. * exposed for testing/performance purposes.
  3413. */
  3414. springs: springs,
  3415. /**
  3416. * Returns settings with which current simulator was initialized
  3417. */
  3418. settings: settings,
  3419. /**
  3420. * Adds a new force to simulation
  3421. */
  3422. addForce: addForce,
  3423. /**
  3424. * Removes a force from the simulation.
  3425. */
  3426. removeForce: removeForce,
  3427. /**
  3428. * Returns a map of all registered forces.
  3429. */
  3430. getForces: getForces,
  3431. /**
  3432. * Performs one step of force simulation.
  3433. *
  3434. * @returns {boolean} true if system is considered stable; False otherwise.
  3435. */
  3436. step: function () {
  3437. for (var i = 0; i < forces.length; ++i) {
  3438. forces[i](iterationNumber);
  3439. }
  3440. var movement = integrate(bodies, settings.timeStep, settings.adaptiveTimeStepWeight);
  3441. iterationNumber += 1;
  3442. return movement;
  3443. },
  3444. /**
  3445. * Adds body to the system
  3446. *
  3447. * @param {ngraph.physics.primitives.Body} body physical body
  3448. *
  3449. * @returns {ngraph.physics.primitives.Body} added body
  3450. */
  3451. addBody: function (body) {
  3452. if (!body) {
  3453. throw new Error('Body is required');
  3454. }
  3455. bodies.push(body);
  3456. return body;
  3457. },
  3458. /**
  3459. * Adds body to the system at given position
  3460. *
  3461. * @param {Object} pos position of a body
  3462. *
  3463. * @returns {ngraph.physics.primitives.Body} added body
  3464. */
  3465. addBodyAt: function (pos) {
  3466. if (!pos) {
  3467. throw new Error('Body position is required');
  3468. }
  3469. var body = createBody(pos);
  3470. bodies.push(body);
  3471. return body;
  3472. },
  3473. /**
  3474. * Removes body from the system
  3475. *
  3476. * @param {ngraph.physics.primitives.Body} body to remove
  3477. *
  3478. * @returns {Boolean} true if body found and removed. falsy otherwise;
  3479. */
  3480. removeBody: function (body) {
  3481. if (!body) { return; }
  3482. var idx = bodies.indexOf(body);
  3483. if (idx < 0) { return; }
  3484. bodies.splice(idx, 1);
  3485. if (bodies.length === 0) {
  3486. bounds.reset();
  3487. }
  3488. return true;
  3489. },
  3490. /**
  3491. * Adds a spring to this simulation.
  3492. *
  3493. * @returns {Object} - a handle for a spring. If you want to later remove
  3494. * spring pass it to removeSpring() method.
  3495. */
  3496. addSpring: function (body1, body2, springLength, springCoefficient) {
  3497. if (!body1 || !body2) {
  3498. throw new Error('Cannot add null spring to force simulator');
  3499. }
  3500. if (typeof springLength !== 'number') {
  3501. springLength = -1; // assume global configuration
  3502. }
  3503. var spring = new Spring(body1, body2, springLength, springCoefficient >= 0 ? springCoefficient : -1);
  3504. springs.push(spring);
  3505. // TODO: could mark simulator as dirty.
  3506. return spring;
  3507. },
  3508. /**
  3509. * Returns amount of movement performed on last step() call
  3510. */
  3511. getTotalMovement: function () {
  3512. return totalMovement;
  3513. },
  3514. /**
  3515. * Removes spring from the system
  3516. *
  3517. * @param {Object} spring to remove. Spring is an object returned by addSpring
  3518. *
  3519. * @returns {Boolean} true if spring found and removed. falsy otherwise;
  3520. */
  3521. removeSpring: function (spring) {
  3522. if (!spring) { return; }
  3523. var idx = springs.indexOf(spring);
  3524. if (idx > -1) {
  3525. springs.splice(idx, 1);
  3526. return true;
  3527. }
  3528. },
  3529. getBestNewBodyPosition: function (neighbors) {
  3530. return bounds.getBestNewPosition(neighbors);
  3531. },
  3532. /**
  3533. * Returns bounding box which covers all bodies
  3534. */
  3535. getBBox: getBoundingBox,
  3536. getBoundingBox: getBoundingBox,
  3537. invalidateBBox: function () {
  3538. console.warn('invalidateBBox() is deprecated, bounds always recomputed on `getBBox()` call');
  3539. },
  3540. // TODO: Move the force specific stuff to force
  3541. gravity: function (value) {
  3542. if (value !== undefined) {
  3543. settings.gravity = value;
  3544. quadTree.options({gravity: value});
  3545. return this;
  3546. } else {
  3547. return settings.gravity;
  3548. }
  3549. },
  3550. theta: function (value) {
  3551. if (value !== undefined) {
  3552. settings.theta = value;
  3553. quadTree.options({theta: value});
  3554. return this;
  3555. } else {
  3556. return settings.theta;
  3557. }
  3558. },
  3559. /**
  3560. * Returns pseudo-random number generator instance.
  3561. */
  3562. random: random
  3563. };
  3564. // allow settings modification via public API:
  3565. expose(settings, publicApi);
  3566. eventify(publicApi);
  3567. return publicApi;
  3568. function getBoundingBox() {
  3569. bounds.update();
  3570. return bounds.box;
  3571. }
  3572. function addForce(forceName, forceFunction) {
  3573. if (forceMap.has(forceName)) throw new Error('Force ' + forceName + ' is already added');
  3574. forceMap.set(forceName, forceFunction);
  3575. forces.push(forceFunction);
  3576. }
  3577. function removeForce(forceName) {
  3578. var forceIndex = forces.indexOf(forceMap.get(forceName));
  3579. if (forceIndex < 0) return;
  3580. forces.splice(forceIndex, 1);
  3581. forceMap.delete(forceName);
  3582. }
  3583. function getForces() {
  3584. // TODO: Should I trust them or clone the forces?
  3585. return forceMap;
  3586. }
  3587. function nbodyForce(/* iterationUmber */) {
  3588. if (bodies.length === 0) return;
  3589. quadTree.insertBodies(bodies);
  3590. var i = bodies.length;
  3591. while (i--) {
  3592. var body = bodies[i];
  3593. if (!body.isPinned) {
  3594. body.reset();
  3595. quadTree.updateBodyForce(body);
  3596. dragForce.update(body);
  3597. }
  3598. }
  3599. }
  3600. function updateSpringForce() {
  3601. var i = springs.length;
  3602. while (i--) {
  3603. springForce.update(springs[i]);
  3604. }
  3605. }
  3606. }
  3607. function expose(settings, target) {
  3608. for (var key in settings) {
  3609. augment(settings, target, key);
  3610. }
  3611. }
  3612. function augment(source, target, key) {
  3613. if (!source.hasOwnProperty(key)) return;
  3614. if (typeof target[key] === 'function') {
  3615. // this accessor is already defined. Ignore it
  3616. return;
  3617. }
  3618. var sourceIsNumber = Number.isFinite(source[key]);
  3619. if (sourceIsNumber) {
  3620. target[key] = function (value) {
  3621. if (value !== undefined) {
  3622. if (!Number.isFinite(value)) throw new Error('Value of ' + key + ' should be a valid number.');
  3623. source[key] = value;
  3624. return target;
  3625. }
  3626. return source[key];
  3627. };
  3628. } else {
  3629. target[key] = function (value) {
  3630. if (value !== undefined) {
  3631. source[key] = value;
  3632. return target;
  3633. }
  3634. return source[key];
  3635. };
  3636. }
  3637. }
  3638. ngraph_forcelayout.exports = createLayout;
  3639. ngraph_forcelayout.exports.simulator = createPhysicsSimulator_1;
  3640. var eventify = ngraph_events;
  3641. /**
  3642. * Creates force based layout for a given graph.
  3643. *
  3644. * @param {ngraph.graph} graph which needs to be laid out
  3645. * @param {object} physicsSettings if you need custom settings
  3646. * for physics simulator you can pass your own settings here. If it's not passed
  3647. * a default one will be created.
  3648. */
  3649. function createLayout(graph, physicsSettings) {
  3650. if (!graph) {
  3651. throw new Error('Graph structure cannot be undefined');
  3652. }
  3653. var createSimulator = (physicsSettings && physicsSettings.createSimulator) || createPhysicsSimulator_1;
  3654. var physicsSimulator = createSimulator(physicsSettings);
  3655. if (Array.isArray(physicsSettings)) throw new Error('Physics settings is expected to be an object');
  3656. var nodeMass = defaultNodeMass;
  3657. if (physicsSettings && typeof physicsSettings.nodeMass === 'function') {
  3658. nodeMass = physicsSettings.nodeMass;
  3659. }
  3660. var nodeBodies = new Map();
  3661. var springs = {};
  3662. var bodiesCount = 0;
  3663. var springTransform = physicsSimulator.settings.springTransform || noop;
  3664. // Initialize physics with what we have in the graph:
  3665. initPhysics();
  3666. listenToEvents();
  3667. var wasStable = false;
  3668. var api = {
  3669. /**
  3670. * Performs one step of iterative layout algorithm
  3671. *
  3672. * @returns {boolean} true if the system should be considered stable; False otherwise.
  3673. * The system is stable if no further call to `step()` can improve the layout.
  3674. */
  3675. step: function() {
  3676. if (bodiesCount === 0) {
  3677. updateStableStatus(true);
  3678. return true;
  3679. }
  3680. var lastMove = physicsSimulator.step();
  3681. // Save the movement in case if someone wants to query it in the step
  3682. // callback.
  3683. api.lastMove = lastMove;
  3684. // Allow listeners to perform low-level actions after nodes are updated.
  3685. api.fire('step');
  3686. var ratio = lastMove/bodiesCount;
  3687. var isStableNow = ratio <= 0.01; // TODO: The number is somewhat arbitrary...
  3688. updateStableStatus(isStableNow);
  3689. return isStableNow;
  3690. },
  3691. /**
  3692. * For a given `nodeId` returns position
  3693. */
  3694. getNodePosition: function (nodeId) {
  3695. return getInitializedBody(nodeId).pos;
  3696. },
  3697. /**
  3698. * Sets position of a node to a given coordinates
  3699. * @param {string} nodeId node identifier
  3700. * @param {number} x position of a node
  3701. * @param {number} y position of a node
  3702. * @param {number=} z position of node (only if applicable to body)
  3703. */
  3704. setNodePosition: function (nodeId) {
  3705. var body = getInitializedBody(nodeId);
  3706. body.setPosition.apply(body, Array.prototype.slice.call(arguments, 1));
  3707. },
  3708. /**
  3709. * @returns {Object} Link position by link id
  3710. * @returns {Object.from} {x, y} coordinates of link start
  3711. * @returns {Object.to} {x, y} coordinates of link end
  3712. */
  3713. getLinkPosition: function (linkId) {
  3714. var spring = springs[linkId];
  3715. if (spring) {
  3716. return {
  3717. from: spring.from.pos,
  3718. to: spring.to.pos
  3719. };
  3720. }
  3721. },
  3722. /**
  3723. * @returns {Object} area required to fit in the graph. Object contains
  3724. * `x1`, `y1` - top left coordinates
  3725. * `x2`, `y2` - bottom right coordinates
  3726. */
  3727. getGraphRect: function () {
  3728. return physicsSimulator.getBBox();
  3729. },
  3730. /**
  3731. * Iterates over each body in the layout simulator and performs a callback(body, nodeId)
  3732. */
  3733. forEachBody: forEachBody,
  3734. /*
  3735. * Requests layout algorithm to pin/unpin node to its current position
  3736. * Pinned nodes should not be affected by layout algorithm and always
  3737. * remain at their position
  3738. */
  3739. pinNode: function (node, isPinned) {
  3740. var body = getInitializedBody(node.id);
  3741. body.isPinned = !!isPinned;
  3742. },
  3743. /**
  3744. * Checks whether given graph's node is currently pinned
  3745. */
  3746. isNodePinned: function (node) {
  3747. return getInitializedBody(node.id).isPinned;
  3748. },
  3749. /**
  3750. * Request to release all resources
  3751. */
  3752. dispose: function() {
  3753. graph.off('changed', onGraphChanged);
  3754. api.fire('disposed');
  3755. },
  3756. /**
  3757. * Gets physical body for a given node id. If node is not found undefined
  3758. * value is returned.
  3759. */
  3760. getBody: getBody,
  3761. /**
  3762. * Gets spring for a given edge.
  3763. *
  3764. * @param {string} linkId link identifer. If two arguments are passed then
  3765. * this argument is treated as formNodeId
  3766. * @param {string=} toId when defined this parameter denotes head of the link
  3767. * and first argument is treated as tail of the link (fromId)
  3768. */
  3769. getSpring: getSpring,
  3770. /**
  3771. * Returns length of cumulative force vector. The closer this to zero - the more stable the system is
  3772. */
  3773. getForceVectorLength: getForceVectorLength,
  3774. /**
  3775. * [Read only] Gets current physics simulator
  3776. */
  3777. simulator: physicsSimulator,
  3778. /**
  3779. * Gets the graph that was used for layout
  3780. */
  3781. graph: graph,
  3782. /**
  3783. * Gets amount of movement performed during last step operation
  3784. */
  3785. lastMove: 0
  3786. };
  3787. eventify(api);
  3788. return api;
  3789. function updateStableStatus(isStableNow) {
  3790. if (wasStable !== isStableNow) {
  3791. wasStable = isStableNow;
  3792. onStableChanged(isStableNow);
  3793. }
  3794. }
  3795. function forEachBody(cb) {
  3796. nodeBodies.forEach(cb);
  3797. }
  3798. function getForceVectorLength() {
  3799. var fx = 0, fy = 0;
  3800. forEachBody(function(body) {
  3801. fx += Math.abs(body.force.x);
  3802. fy += Math.abs(body.force.y);
  3803. });
  3804. return Math.sqrt(fx * fx + fy * fy);
  3805. }
  3806. function getSpring(fromId, toId) {
  3807. var linkId;
  3808. if (toId === undefined) {
  3809. if (typeof fromId !== 'object') {
  3810. // assume fromId as a linkId:
  3811. linkId = fromId;
  3812. } else {
  3813. // assume fromId to be a link object:
  3814. linkId = fromId.id;
  3815. }
  3816. } else {
  3817. // toId is defined, should grab link:
  3818. var link = graph.hasLink(fromId, toId);
  3819. if (!link) return;
  3820. linkId = link.id;
  3821. }
  3822. return springs[linkId];
  3823. }
  3824. function getBody(nodeId) {
  3825. return nodeBodies.get(nodeId);
  3826. }
  3827. function listenToEvents() {
  3828. graph.on('changed', onGraphChanged);
  3829. }
  3830. function onStableChanged(isStable) {
  3831. api.fire('stable', isStable);
  3832. }
  3833. function onGraphChanged(changes) {
  3834. for (var i = 0; i < changes.length; ++i) {
  3835. var change = changes[i];
  3836. if (change.changeType === 'add') {
  3837. if (change.node) {
  3838. initBody(change.node.id);
  3839. }
  3840. if (change.link) {
  3841. initLink(change.link);
  3842. }
  3843. } else if (change.changeType === 'remove') {
  3844. if (change.node) {
  3845. releaseNode(change.node);
  3846. }
  3847. if (change.link) {
  3848. releaseLink(change.link);
  3849. }
  3850. }
  3851. }
  3852. bodiesCount = graph.getNodesCount();
  3853. }
  3854. function initPhysics() {
  3855. bodiesCount = 0;
  3856. graph.forEachNode(function (node) {
  3857. initBody(node.id);
  3858. bodiesCount += 1;
  3859. });
  3860. graph.forEachLink(initLink);
  3861. }
  3862. function initBody(nodeId) {
  3863. var body = nodeBodies.get(nodeId);
  3864. if (!body) {
  3865. var node = graph.getNode(nodeId);
  3866. if (!node) {
  3867. throw new Error('initBody() was called with unknown node id');
  3868. }
  3869. var pos = node.position;
  3870. if (!pos) {
  3871. var neighbors = getNeighborBodies(node);
  3872. pos = physicsSimulator.getBestNewBodyPosition(neighbors);
  3873. }
  3874. body = physicsSimulator.addBodyAt(pos);
  3875. body.id = nodeId;
  3876. nodeBodies.set(nodeId, body);
  3877. updateBodyMass(nodeId);
  3878. if (isNodeOriginallyPinned(node)) {
  3879. body.isPinned = true;
  3880. }
  3881. }
  3882. }
  3883. function releaseNode(node) {
  3884. var nodeId = node.id;
  3885. var body = nodeBodies.get(nodeId);
  3886. if (body) {
  3887. nodeBodies.delete(nodeId);
  3888. physicsSimulator.removeBody(body);
  3889. }
  3890. }
  3891. function initLink(link) {
  3892. updateBodyMass(link.fromId);
  3893. updateBodyMass(link.toId);
  3894. var fromBody = nodeBodies.get(link.fromId),
  3895. toBody = nodeBodies.get(link.toId),
  3896. spring = physicsSimulator.addSpring(fromBody, toBody, link.length);
  3897. springTransform(link, spring);
  3898. springs[link.id] = spring;
  3899. }
  3900. function releaseLink(link) {
  3901. var spring = springs[link.id];
  3902. if (spring) {
  3903. var from = graph.getNode(link.fromId),
  3904. to = graph.getNode(link.toId);
  3905. if (from) updateBodyMass(from.id);
  3906. if (to) updateBodyMass(to.id);
  3907. delete springs[link.id];
  3908. physicsSimulator.removeSpring(spring);
  3909. }
  3910. }
  3911. function getNeighborBodies(node) {
  3912. // TODO: Could probably be done better on memory
  3913. var neighbors = [];
  3914. if (!node.links) {
  3915. return neighbors;
  3916. }
  3917. var maxNeighbors = Math.min(node.links.length, 2);
  3918. for (var i = 0; i < maxNeighbors; ++i) {
  3919. var link = node.links[i];
  3920. var otherBody = link.fromId !== node.id ? nodeBodies.get(link.fromId) : nodeBodies.get(link.toId);
  3921. if (otherBody && otherBody.pos) {
  3922. neighbors.push(otherBody);
  3923. }
  3924. }
  3925. return neighbors;
  3926. }
  3927. function updateBodyMass(nodeId) {
  3928. var body = nodeBodies.get(nodeId);
  3929. body.mass = nodeMass(nodeId);
  3930. if (Number.isNaN(body.mass)) {
  3931. throw new Error('Node mass should be a number');
  3932. }
  3933. }
  3934. /**
  3935. * Checks whether graph node has in its settings pinned attribute,
  3936. * which means layout algorithm cannot move it. Node can be marked
  3937. * as pinned, if it has "isPinned" attribute, or when node.data has it.
  3938. *
  3939. * @param {Object} node a graph node to check
  3940. * @return {Boolean} true if node should be treated as pinned; false otherwise.
  3941. */
  3942. function isNodeOriginallyPinned(node) {
  3943. return (node && (node.isPinned || (node.data && node.data.isPinned)));
  3944. }
  3945. function getInitializedBody(nodeId) {
  3946. var body = nodeBodies.get(nodeId);
  3947. if (!body) {
  3948. initBody(nodeId);
  3949. body = nodeBodies.get(nodeId);
  3950. }
  3951. return body;
  3952. }
  3953. /**
  3954. * Calculates mass of a body, which corresponds to node with given id.
  3955. *
  3956. * @param {String|Number} nodeId identifier of a node, for which body mass needs to be calculated
  3957. * @returns {Number} recommended mass of the body;
  3958. */
  3959. function defaultNodeMass(nodeId) {
  3960. var links = graph.getLinks(nodeId);
  3961. if (!links) return 1;
  3962. return 1 + links.length / 3.0;
  3963. }
  3964. }
  3965. function noop() { }
  3966. var forcelayout = ngraph_forcelayout.exports;
  3967. /**
  3968. * Returns a function, that, as long as it continues to be invoked, will not
  3969. * be triggered. The function will be called after it stops being called for
  3970. * N milliseconds. If `immediate` is passed, trigger the function on the
  3971. * leading edge, instead of the trailing. The function also has a property 'clear'
  3972. * that is a function which will clear the timer to prevent previously scheduled executions.
  3973. *
  3974. * @source underscore.js
  3975. * @see http://unscriptable.com/2009/03/20/debouncing-javascript-methods/
  3976. * @param {Function} function to wrap
  3977. * @param {Number} timeout in ms (`100`)
  3978. * @param {Boolean} whether to execute at the beginning (`false`)
  3979. * @api public
  3980. */
  3981. function debounce(func, wait, immediate){
  3982. var timeout, args, context, timestamp, result;
  3983. if (null == wait) wait = 100;
  3984. function later() {
  3985. var last = Date.now() - timestamp;
  3986. if (last < wait && last >= 0) {
  3987. timeout = setTimeout(later, wait - last);
  3988. } else {
  3989. timeout = null;
  3990. if (!immediate) {
  3991. result = func.apply(context, args);
  3992. context = args = null;
  3993. }
  3994. }
  3995. }
  3996. var debounced = function(){
  3997. context = this;
  3998. args = arguments;
  3999. timestamp = Date.now();
  4000. var callNow = immediate && !timeout;
  4001. if (!timeout) timeout = setTimeout(later, wait);
  4002. if (callNow) {
  4003. result = func.apply(context, args);
  4004. context = args = null;
  4005. }
  4006. return result;
  4007. };
  4008. debounced.clear = function() {
  4009. if (timeout) {
  4010. clearTimeout(timeout);
  4011. timeout = null;
  4012. }
  4013. };
  4014. debounced.flush = function() {
  4015. if (timeout) {
  4016. result = func.apply(context, args);
  4017. context = args = null;
  4018. clearTimeout(timeout);
  4019. timeout = null;
  4020. }
  4021. };
  4022. return debounced;
  4023. }
  4024. // Adds compatibility for ES modules
  4025. debounce.debounce = debounce;
  4026. var debounce_1 = debounce;
  4027. function _classCallCheck(instance, Constructor) {
  4028. if (!(instance instanceof Constructor)) {
  4029. throw new TypeError("Cannot call a class as a function");
  4030. }
  4031. }
  4032. function _slicedToArray$2(arr, i) {
  4033. return _arrayWithHoles$2(arr) || _iterableToArrayLimit$2(arr, i) || _unsupportedIterableToArray$2(arr, i) || _nonIterableRest$2();
  4034. }
  4035. function _arrayWithHoles$2(arr) {
  4036. if (Array.isArray(arr)) return arr;
  4037. }
  4038. function _iterableToArrayLimit$2(arr, i) {
  4039. var _i = arr && (typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]);
  4040. if (_i == null) return;
  4041. var _arr = [];
  4042. var _n = true;
  4043. var _d = false;
  4044. var _s, _e;
  4045. try {
  4046. for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) {
  4047. _arr.push(_s.value);
  4048. if (i && _arr.length === i) break;
  4049. }
  4050. } catch (err) {
  4051. _d = true;
  4052. _e = err;
  4053. } finally {
  4054. try {
  4055. if (!_n && _i["return"] != null) _i["return"]();
  4056. } finally {
  4057. if (_d) throw _e;
  4058. }
  4059. }
  4060. return _arr;
  4061. }
  4062. function _unsupportedIterableToArray$2(o, minLen) {
  4063. if (!o) return;
  4064. if (typeof o === "string") return _arrayLikeToArray$2(o, minLen);
  4065. var n = Object.prototype.toString.call(o).slice(8, -1);
  4066. if (n === "Object" && o.constructor) n = o.constructor.name;
  4067. if (n === "Map" || n === "Set") return Array.from(o);
  4068. if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$2(o, minLen);
  4069. }
  4070. function _arrayLikeToArray$2(arr, len) {
  4071. if (len == null || len > arr.length) len = arr.length;
  4072. for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
  4073. return arr2;
  4074. }
  4075. function _nonIterableRest$2() {
  4076. throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
  4077. }
  4078. var Prop = function Prop(name, _ref) {
  4079. var _ref$default = _ref["default"],
  4080. defaultVal = _ref$default === void 0 ? null : _ref$default,
  4081. _ref$triggerUpdate = _ref.triggerUpdate,
  4082. triggerUpdate = _ref$triggerUpdate === void 0 ? true : _ref$triggerUpdate,
  4083. _ref$onChange = _ref.onChange,
  4084. onChange = _ref$onChange === void 0 ? function (newVal, state) {} : _ref$onChange;
  4085. _classCallCheck(this, Prop);
  4086. this.name = name;
  4087. this.defaultVal = defaultVal;
  4088. this.triggerUpdate = triggerUpdate;
  4089. this.onChange = onChange;
  4090. };
  4091. function index$2 (_ref2) {
  4092. var _ref2$stateInit = _ref2.stateInit,
  4093. stateInit = _ref2$stateInit === void 0 ? function () {
  4094. return {};
  4095. } : _ref2$stateInit,
  4096. _ref2$props = _ref2.props,
  4097. rawProps = _ref2$props === void 0 ? {} : _ref2$props,
  4098. _ref2$methods = _ref2.methods,
  4099. methods = _ref2$methods === void 0 ? {} : _ref2$methods,
  4100. _ref2$aliases = _ref2.aliases,
  4101. aliases = _ref2$aliases === void 0 ? {} : _ref2$aliases,
  4102. _ref2$init = _ref2.init,
  4103. initFn = _ref2$init === void 0 ? function () {} : _ref2$init,
  4104. _ref2$update = _ref2.update,
  4105. updateFn = _ref2$update === void 0 ? function () {} : _ref2$update;
  4106. // Parse props into Prop instances
  4107. var props = Object.keys(rawProps).map(function (propName) {
  4108. return new Prop(propName, rawProps[propName]);
  4109. });
  4110. return function () {
  4111. var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  4112. // Holds component state
  4113. var state = Object.assign({}, stateInit instanceof Function ? stateInit(options) : stateInit, // Support plain objects for backwards compatibility
  4114. {
  4115. initialised: false
  4116. }); // keeps track of which props triggered an update
  4117. var changedProps = {}; // Component constructor
  4118. function comp(nodeElement) {
  4119. initStatic(nodeElement, options);
  4120. digest();
  4121. return comp;
  4122. }
  4123. var initStatic = function initStatic(nodeElement, options) {
  4124. initFn.call(comp, nodeElement, state, options);
  4125. state.initialised = true;
  4126. };
  4127. var digest = debounce_1(function () {
  4128. if (!state.initialised) {
  4129. return;
  4130. }
  4131. updateFn.call(comp, state, changedProps);
  4132. changedProps = {};
  4133. }, 1); // Getter/setter methods
  4134. props.forEach(function (prop) {
  4135. comp[prop.name] = getSetProp(prop);
  4136. function getSetProp(_ref3) {
  4137. var prop = _ref3.name,
  4138. _ref3$triggerUpdate = _ref3.triggerUpdate,
  4139. redigest = _ref3$triggerUpdate === void 0 ? false : _ref3$triggerUpdate,
  4140. _ref3$onChange = _ref3.onChange,
  4141. onChange = _ref3$onChange === void 0 ? function (newVal, state) {} : _ref3$onChange,
  4142. _ref3$defaultVal = _ref3.defaultVal,
  4143. defaultVal = _ref3$defaultVal === void 0 ? null : _ref3$defaultVal;
  4144. return function (_) {
  4145. var curVal = state[prop];
  4146. if (!arguments.length) {
  4147. return curVal;
  4148. } // Getter mode
  4149. var val = _ === undefined ? defaultVal : _; // pick default if value passed is undefined
  4150. state[prop] = val;
  4151. onChange.call(comp, val, state, curVal); // track changed props
  4152. !changedProps.hasOwnProperty(prop) && (changedProps[prop] = curVal);
  4153. if (redigest) {
  4154. digest();
  4155. }
  4156. return comp;
  4157. };
  4158. }
  4159. }); // Other methods
  4160. Object.keys(methods).forEach(function (methodName) {
  4161. comp[methodName] = function () {
  4162. var _methods$methodName;
  4163. for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
  4164. args[_key] = arguments[_key];
  4165. }
  4166. return (_methods$methodName = methods[methodName]).call.apply(_methods$methodName, [comp, state].concat(args));
  4167. };
  4168. }); // Link aliases
  4169. Object.entries(aliases).forEach(function (_ref4) {
  4170. var _ref5 = _slicedToArray$2(_ref4, 2),
  4171. alias = _ref5[0],
  4172. target = _ref5[1];
  4173. return comp[alias] = comp[target];
  4174. }); // Reset all component props to their default value
  4175. comp.resetProps = function () {
  4176. props.forEach(function (prop) {
  4177. comp[prop.name](prop.defaultVal);
  4178. });
  4179. return comp;
  4180. }; //
  4181. comp.resetProps(); // Apply all prop defaults
  4182. state._rerender = digest; // Expose digest method
  4183. return comp;
  4184. };
  4185. }
  4186. var index$1 = (function (p) {
  4187. return p instanceof Function ? p // fn
  4188. : typeof p === 'string' ? function (obj) {
  4189. return obj[p];
  4190. } // property name
  4191. : function (obj) {
  4192. return p;
  4193. };
  4194. }); // constant
  4195. class InternMap extends Map {
  4196. constructor(entries, key = keyof) {
  4197. super();
  4198. Object.defineProperties(this, {_intern: {value: new Map()}, _key: {value: key}});
  4199. if (entries != null) for (const [key, value] of entries) this.set(key, value);
  4200. }
  4201. get(key) {
  4202. return super.get(intern_get(this, key));
  4203. }
  4204. has(key) {
  4205. return super.has(intern_get(this, key));
  4206. }
  4207. set(key, value) {
  4208. return super.set(intern_set(this, key), value);
  4209. }
  4210. delete(key) {
  4211. return super.delete(intern_delete(this, key));
  4212. }
  4213. }
  4214. function intern_get({_intern, _key}, value) {
  4215. const key = _key(value);
  4216. return _intern.has(key) ? _intern.get(key) : value;
  4217. }
  4218. function intern_set({_intern, _key}, value) {
  4219. const key = _key(value);
  4220. if (_intern.has(key)) return _intern.get(key);
  4221. _intern.set(key, value);
  4222. return value;
  4223. }
  4224. function intern_delete({_intern, _key}, value) {
  4225. const key = _key(value);
  4226. if (_intern.has(key)) {
  4227. value = _intern.get(value);
  4228. _intern.delete(key);
  4229. }
  4230. return value;
  4231. }
  4232. function keyof(value) {
  4233. return value !== null && typeof value === "object" ? value.valueOf() : value;
  4234. }
  4235. function max(values, valueof) {
  4236. let max;
  4237. if (valueof === undefined) {
  4238. for (const value of values) {
  4239. if (value != null
  4240. && (max < value || (max === undefined && value >= value))) {
  4241. max = value;
  4242. }
  4243. }
  4244. } else {
  4245. let index = -1;
  4246. for (let value of values) {
  4247. if ((value = valueof(value, ++index, values)) != null
  4248. && (max < value || (max === undefined && value >= value))) {
  4249. max = value;
  4250. }
  4251. }
  4252. }
  4253. return max;
  4254. }
  4255. function min(values, valueof) {
  4256. let min;
  4257. if (valueof === undefined) {
  4258. for (const value of values) {
  4259. if (value != null
  4260. && (min > value || (min === undefined && value >= value))) {
  4261. min = value;
  4262. }
  4263. }
  4264. } else {
  4265. let index = -1;
  4266. for (let value of values) {
  4267. if ((value = valueof(value, ++index, values)) != null
  4268. && (min > value || (min === undefined && value >= value))) {
  4269. min = value;
  4270. }
  4271. }
  4272. }
  4273. return min;
  4274. }
  4275. function _objectWithoutPropertiesLoose$1(source, excluded) {
  4276. if (source == null) return {};
  4277. var target = {};
  4278. var sourceKeys = Object.keys(source);
  4279. var key, i;
  4280. for (i = 0; i < sourceKeys.length; i++) {
  4281. key = sourceKeys[i];
  4282. if (excluded.indexOf(key) >= 0) continue;
  4283. target[key] = source[key];
  4284. }
  4285. return target;
  4286. }
  4287. function _objectWithoutProperties$1(source, excluded) {
  4288. if (source == null) return {};
  4289. var target = _objectWithoutPropertiesLoose$1(source, excluded);
  4290. var key, i;
  4291. if (Object.getOwnPropertySymbols) {
  4292. var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
  4293. for (i = 0; i < sourceSymbolKeys.length; i++) {
  4294. key = sourceSymbolKeys[i];
  4295. if (excluded.indexOf(key) >= 0) continue;
  4296. if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
  4297. target[key] = source[key];
  4298. }
  4299. }
  4300. return target;
  4301. }
  4302. function _slicedToArray$1(arr, i) {
  4303. return _arrayWithHoles$1(arr) || _iterableToArrayLimit$1(arr, i) || _unsupportedIterableToArray$1(arr, i) || _nonIterableRest$1();
  4304. }
  4305. function _toConsumableArray$1(arr) {
  4306. return _arrayWithoutHoles$1(arr) || _iterableToArray$1(arr) || _unsupportedIterableToArray$1(arr) || _nonIterableSpread$1();
  4307. }
  4308. function _arrayWithoutHoles$1(arr) {
  4309. if (Array.isArray(arr)) return _arrayLikeToArray$1(arr);
  4310. }
  4311. function _arrayWithHoles$1(arr) {
  4312. if (Array.isArray(arr)) return arr;
  4313. }
  4314. function _iterableToArray$1(iter) {
  4315. if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
  4316. }
  4317. function _iterableToArrayLimit$1(arr, i) {
  4318. var _i = arr && (typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]);
  4319. if (_i == null) return;
  4320. var _arr = [];
  4321. var _n = true;
  4322. var _d = false;
  4323. var _s, _e;
  4324. try {
  4325. for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) {
  4326. _arr.push(_s.value);
  4327. if (i && _arr.length === i) break;
  4328. }
  4329. } catch (err) {
  4330. _d = true;
  4331. _e = err;
  4332. } finally {
  4333. try {
  4334. if (!_n && _i["return"] != null) _i["return"]();
  4335. } finally {
  4336. if (_d) throw _e;
  4337. }
  4338. }
  4339. return _arr;
  4340. }
  4341. function _unsupportedIterableToArray$1(o, minLen) {
  4342. if (!o) return;
  4343. if (typeof o === "string") return _arrayLikeToArray$1(o, minLen);
  4344. var n = Object.prototype.toString.call(o).slice(8, -1);
  4345. if (n === "Object" && o.constructor) n = o.constructor.name;
  4346. if (n === "Map" || n === "Set") return Array.from(o);
  4347. if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$1(o, minLen);
  4348. }
  4349. function _arrayLikeToArray$1(arr, len) {
  4350. if (len == null || len > arr.length) len = arr.length;
  4351. for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
  4352. return arr2;
  4353. }
  4354. function _nonIterableSpread$1() {
  4355. throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
  4356. }
  4357. function _nonIterableRest$1() {
  4358. throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
  4359. }
  4360. function _toPrimitive(input, hint) {
  4361. if (typeof input !== "object" || input === null) return input;
  4362. var prim = input[Symbol.toPrimitive];
  4363. if (prim !== undefined) {
  4364. var res = prim.call(input, hint || "default");
  4365. if (typeof res !== "object") return res;
  4366. throw new TypeError("@@toPrimitive must return a primitive value.");
  4367. }
  4368. return (hint === "string" ? String : Number)(input);
  4369. }
  4370. function _toPropertyKey(arg) {
  4371. var key = _toPrimitive(arg, "string");
  4372. return typeof key === "symbol" ? key : String(key);
  4373. }
  4374. var index = (function () {
  4375. var list = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  4376. var keyAccessors = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
  4377. var multiItem = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
  4378. var flattenKeys = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
  4379. var keys = (keyAccessors instanceof Array ? keyAccessors.length ? keyAccessors : [undefined] : [keyAccessors]).map(function (key) {
  4380. return {
  4381. keyAccessor: key,
  4382. isProp: !(key instanceof Function)
  4383. };
  4384. });
  4385. var indexedResult = list.reduce(function (res, item) {
  4386. var iterObj = res;
  4387. var itemVal = item;
  4388. keys.forEach(function (_ref, idx) {
  4389. var keyAccessor = _ref.keyAccessor,
  4390. isProp = _ref.isProp;
  4391. var key;
  4392. if (isProp) {
  4393. var _itemVal = itemVal,
  4394. propVal = _itemVal[keyAccessor],
  4395. rest = _objectWithoutProperties$1(_itemVal, [keyAccessor].map(_toPropertyKey));
  4396. key = propVal;
  4397. itemVal = rest;
  4398. } else {
  4399. key = keyAccessor(itemVal, idx);
  4400. }
  4401. if (idx + 1 < keys.length) {
  4402. if (!iterObj.hasOwnProperty(key)) {
  4403. iterObj[key] = {};
  4404. }
  4405. iterObj = iterObj[key];
  4406. } else {
  4407. // Leaf key
  4408. if (multiItem) {
  4409. if (!iterObj.hasOwnProperty(key)) {
  4410. iterObj[key] = [];
  4411. }
  4412. iterObj[key].push(itemVal);
  4413. } else {
  4414. iterObj[key] = itemVal;
  4415. }
  4416. }
  4417. });
  4418. return res;
  4419. }, {});
  4420. if (multiItem instanceof Function) {
  4421. // Reduce leaf multiple values
  4422. (function reduce(node) {
  4423. var level = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
  4424. if (level === keys.length) {
  4425. Object.keys(node).forEach(function (k) {
  4426. return node[k] = multiItem(node[k]);
  4427. });
  4428. } else {
  4429. Object.values(node).forEach(function (child) {
  4430. return reduce(child, level + 1);
  4431. });
  4432. }
  4433. })(indexedResult); // IIFE
  4434. }
  4435. var result = indexedResult;
  4436. if (flattenKeys) {
  4437. // flatten into array
  4438. result = [];
  4439. (function flatten(node) {
  4440. var accKeys = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
  4441. if (accKeys.length === keys.length) {
  4442. result.push({
  4443. keys: accKeys,
  4444. vals: node
  4445. });
  4446. } else {
  4447. Object.entries(node).forEach(function (_ref2) {
  4448. var _ref3 = _slicedToArray$1(_ref2, 2),
  4449. key = _ref3[0],
  4450. val = _ref3[1];
  4451. return flatten(val, [].concat(_toConsumableArray$1(accKeys), [key]));
  4452. });
  4453. }
  4454. })(indexedResult); //IIFE
  4455. if (keyAccessors instanceof Array && keyAccessors.length === 0 && result.length === 1) {
  4456. // clear keys if there's no key accessors (single result)
  4457. result[0].keys = [];
  4458. }
  4459. }
  4460. return result;
  4461. });
  4462. function ownKeys(object, enumerableOnly) {
  4463. var keys = Object.keys(object);
  4464. if (Object.getOwnPropertySymbols) {
  4465. var symbols = Object.getOwnPropertySymbols(object);
  4466. if (enumerableOnly) {
  4467. symbols = symbols.filter(function (sym) {
  4468. return Object.getOwnPropertyDescriptor(object, sym).enumerable;
  4469. });
  4470. }
  4471. keys.push.apply(keys, symbols);
  4472. }
  4473. return keys;
  4474. }
  4475. function _objectSpread2(target) {
  4476. for (var i = 1; i < arguments.length; i++) {
  4477. var source = arguments[i] != null ? arguments[i] : {};
  4478. if (i % 2) {
  4479. ownKeys(Object(source), true).forEach(function (key) {
  4480. _defineProperty(target, key, source[key]);
  4481. });
  4482. } else if (Object.getOwnPropertyDescriptors) {
  4483. Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
  4484. } else {
  4485. ownKeys(Object(source)).forEach(function (key) {
  4486. Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
  4487. });
  4488. }
  4489. }
  4490. return target;
  4491. }
  4492. function _defineProperty(obj, key, value) {
  4493. if (key in obj) {
  4494. Object.defineProperty(obj, key, {
  4495. value: value,
  4496. enumerable: true,
  4497. configurable: true,
  4498. writable: true
  4499. });
  4500. } else {
  4501. obj[key] = value;
  4502. }
  4503. return obj;
  4504. }
  4505. function _objectWithoutPropertiesLoose(source, excluded) {
  4506. if (source == null) return {};
  4507. var target = {};
  4508. var sourceKeys = Object.keys(source);
  4509. var key, i;
  4510. for (i = 0; i < sourceKeys.length; i++) {
  4511. key = sourceKeys[i];
  4512. if (excluded.indexOf(key) >= 0) continue;
  4513. target[key] = source[key];
  4514. }
  4515. return target;
  4516. }
  4517. function _objectWithoutProperties(source, excluded) {
  4518. if (source == null) return {};
  4519. var target = _objectWithoutPropertiesLoose(source, excluded);
  4520. var key, i;
  4521. if (Object.getOwnPropertySymbols) {
  4522. var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
  4523. for (i = 0; i < sourceSymbolKeys.length; i++) {
  4524. key = sourceSymbolKeys[i];
  4525. if (excluded.indexOf(key) >= 0) continue;
  4526. if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
  4527. target[key] = source[key];
  4528. }
  4529. }
  4530. return target;
  4531. }
  4532. function _slicedToArray(arr, i) {
  4533. return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
  4534. }
  4535. function _toConsumableArray(arr) {
  4536. return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
  4537. }
  4538. function _arrayWithoutHoles(arr) {
  4539. if (Array.isArray(arr)) return _arrayLikeToArray(arr);
  4540. }
  4541. function _arrayWithHoles(arr) {
  4542. if (Array.isArray(arr)) return arr;
  4543. }
  4544. function _iterableToArray(iter) {
  4545. if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
  4546. }
  4547. function _iterableToArrayLimit(arr, i) {
  4548. var _i = arr && (typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]);
  4549. if (_i == null) return;
  4550. var _arr = [];
  4551. var _n = true;
  4552. var _d = false;
  4553. var _s, _e;
  4554. try {
  4555. for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) {
  4556. _arr.push(_s.value);
  4557. if (i && _arr.length === i) break;
  4558. }
  4559. } catch (err) {
  4560. _d = true;
  4561. _e = err;
  4562. } finally {
  4563. try {
  4564. if (!_n && _i["return"] != null) _i["return"]();
  4565. } finally {
  4566. if (_d) throw _e;
  4567. }
  4568. }
  4569. return _arr;
  4570. }
  4571. function _unsupportedIterableToArray(o, minLen) {
  4572. if (!o) return;
  4573. if (typeof o === "string") return _arrayLikeToArray(o, minLen);
  4574. var n = Object.prototype.toString.call(o).slice(8, -1);
  4575. if (n === "Object" && o.constructor) n = o.constructor.name;
  4576. if (n === "Map" || n === "Set") return Array.from(o);
  4577. if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
  4578. }
  4579. function _arrayLikeToArray(arr, len) {
  4580. if (len == null || len > arr.length) len = arr.length;
  4581. for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
  4582. return arr2;
  4583. }
  4584. function _nonIterableSpread() {
  4585. throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
  4586. }
  4587. function _nonIterableRest() {
  4588. throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
  4589. }
  4590. function diffArrays(prev, next, idAccessor) {
  4591. var result = {
  4592. enter: [],
  4593. update: [],
  4594. exit: []
  4595. };
  4596. if (!idAccessor) {
  4597. // use object references for comparison
  4598. var prevSet = new Set(prev);
  4599. var nextSet = new Set(next);
  4600. new Set([].concat(_toConsumableArray(prevSet), _toConsumableArray(nextSet))).forEach(function (item) {
  4601. var type = !prevSet.has(item) ? 'enter' : !nextSet.has(item) ? 'exit' : 'update';
  4602. result[type].push(type === 'update' ? [item, item] : item);
  4603. });
  4604. } else {
  4605. // compare by id (duplicate keys are ignored)
  4606. var prevById = index(prev, idAccessor, false);
  4607. var nextById = index(next, idAccessor, false);
  4608. var byId = Object.assign({}, prevById, nextById);
  4609. Object.entries(byId).forEach(function (_ref) {
  4610. var _ref2 = _slicedToArray(_ref, 2),
  4611. id = _ref2[0],
  4612. item = _ref2[1];
  4613. var type = !prevById.hasOwnProperty(id) ? 'enter' : !nextById.hasOwnProperty(id) ? 'exit' : 'update';
  4614. result[type].push(type === 'update' ? [prevById[id], nextById[id]] : item);
  4615. });
  4616. }
  4617. return result;
  4618. }
  4619. function dataBindDiff(data, existingObjs, _ref3) {
  4620. var _ref3$objBindAttr = _ref3.objBindAttr,
  4621. objBindAttr = _ref3$objBindAttr === void 0 ? '__obj' : _ref3$objBindAttr,
  4622. _ref3$dataBindAttr = _ref3.dataBindAttr,
  4623. dataBindAttr = _ref3$dataBindAttr === void 0 ? '__data' : _ref3$dataBindAttr,
  4624. idAccessor = _ref3.idAccessor,
  4625. _ref3$purge = _ref3.purge,
  4626. purge = _ref3$purge === void 0 ? false : _ref3$purge;
  4627. var isObjValid = function isObjValid(obj) {
  4628. return obj.hasOwnProperty(dataBindAttr);
  4629. };
  4630. var removeObjs = existingObjs.filter(function (obj) {
  4631. return !isObjValid(obj);
  4632. });
  4633. var prevD = existingObjs.filter(isObjValid).map(function (obj) {
  4634. return obj[dataBindAttr];
  4635. });
  4636. var nextD = data;
  4637. var diff = purge ? {
  4638. enter: nextD,
  4639. exit: prevD,
  4640. update: []
  4641. } // don't diff data in purge mode
  4642. : diffArrays(prevD, nextD, idAccessor);
  4643. diff.update = diff.update.map(function (_ref4) {
  4644. var _ref5 = _slicedToArray(_ref4, 2),
  4645. prevD = _ref5[0],
  4646. nextD = _ref5[1];
  4647. if (prevD !== nextD) {
  4648. // transfer obj to new data point (if different)
  4649. nextD[objBindAttr] = prevD[objBindAttr];
  4650. nextD[objBindAttr][dataBindAttr] = nextD;
  4651. }
  4652. return nextD;
  4653. });
  4654. diff.exit = diff.exit.concat(removeObjs.map(function (obj) {
  4655. return _defineProperty({}, objBindAttr, obj);
  4656. }));
  4657. return diff;
  4658. }
  4659. function viewDigest(data, existingObjs, // list
  4660. appendObj, // item => {...} function
  4661. removeObj, // item => {...} function
  4662. _ref7) {
  4663. var _ref7$createObj = _ref7.createObj,
  4664. createObj = _ref7$createObj === void 0 ? function (d) {
  4665. return {};
  4666. } : _ref7$createObj,
  4667. _ref7$updateObj = _ref7.updateObj,
  4668. updateObj = _ref7$updateObj === void 0 ? function (obj, d) {} : _ref7$updateObj,
  4669. _ref7$exitObj = _ref7.exitObj,
  4670. exitObj = _ref7$exitObj === void 0 ? function (obj) {} : _ref7$exitObj,
  4671. _ref7$objBindAttr = _ref7.objBindAttr,
  4672. objBindAttr = _ref7$objBindAttr === void 0 ? '__obj' : _ref7$objBindAttr,
  4673. _ref7$dataBindAttr = _ref7.dataBindAttr,
  4674. dataBindAttr = _ref7$dataBindAttr === void 0 ? '__data' : _ref7$dataBindAttr,
  4675. dataDiffOptions = _objectWithoutProperties(_ref7, ["createObj", "updateObj", "exitObj", "objBindAttr", "dataBindAttr"]);
  4676. var _dataBindDiff = dataBindDiff(data, existingObjs, _objectSpread2({
  4677. objBindAttr: objBindAttr,
  4678. dataBindAttr: dataBindAttr
  4679. }, dataDiffOptions)),
  4680. enter = _dataBindDiff.enter,
  4681. update = _dataBindDiff.update,
  4682. exit = _dataBindDiff.exit; // Remove exiting points
  4683. exit.forEach(function (d) {
  4684. var obj = d[objBindAttr];
  4685. delete d[objBindAttr]; // unbind obj
  4686. exitObj(obj);
  4687. removeObj(obj);
  4688. });
  4689. var newObjs = createObjs(enter);
  4690. var pointsData = [].concat(_toConsumableArray(enter), _toConsumableArray(update));
  4691. updateObjs(pointsData); // Add new points
  4692. newObjs.forEach(appendObj); //
  4693. function createObjs(data) {
  4694. var newObjs = [];
  4695. data.forEach(function (d) {
  4696. var obj = createObj(d);
  4697. if (obj) {
  4698. obj[dataBindAttr] = d;
  4699. d[objBindAttr] = obj;
  4700. newObjs.push(obj);
  4701. }
  4702. });
  4703. return newObjs;
  4704. }
  4705. function updateObjs(data) {
  4706. data.forEach(function (d) {
  4707. var obj = d[objBindAttr];
  4708. if (obj) {
  4709. obj[dataBindAttr] = d;
  4710. updateObj(obj, d);
  4711. }
  4712. });
  4713. }
  4714. }
  4715. var materialDispose = function materialDispose(material) {
  4716. if (material instanceof Array) {
  4717. material.forEach(materialDispose);
  4718. } else {
  4719. if (material.map) {
  4720. material.map.dispose();
  4721. }
  4722. material.dispose();
  4723. }
  4724. };
  4725. var deallocate = function deallocate(obj) {
  4726. if (obj.geometry) {
  4727. obj.geometry.dispose();
  4728. }
  4729. if (obj.material) {
  4730. materialDispose(obj.material);
  4731. }
  4732. if (obj.texture) {
  4733. obj.texture.dispose();
  4734. }
  4735. if (obj.children) {
  4736. obj.children.forEach(deallocate);
  4737. }
  4738. };
  4739. var emptyObject = function emptyObject(obj) {
  4740. while (obj.children.length) {
  4741. var childObj = obj.children[0];
  4742. obj.remove(childObj);
  4743. deallocate(childObj);
  4744. }
  4745. };
  4746. var _excluded = ["objFilter"];
  4747. function threeDigest(data, scene) {
  4748. var _ref = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  4749. var _ref$objFilter = _ref.objFilter,
  4750. objFilter = _ref$objFilter === void 0 ? function () {
  4751. return true;
  4752. } : _ref$objFilter,
  4753. options = _objectWithoutProperties$2(_ref, _excluded);
  4754. return viewDigest(data, scene.children.filter(objFilter), function (obj) {
  4755. return scene.add(obj);
  4756. }, function (obj) {
  4757. scene.remove(obj);
  4758. emptyObject(obj);
  4759. }, _objectSpread2$1({
  4760. objBindAttr: '__threeObj'
  4761. }, options));
  4762. }
  4763. function initRange(domain, range) {
  4764. switch (arguments.length) {
  4765. case 0: break;
  4766. case 1: this.range(domain); break;
  4767. default: this.range(range).domain(domain); break;
  4768. }
  4769. return this;
  4770. }
  4771. const implicit = Symbol("implicit");
  4772. function ordinal() {
  4773. var index = new InternMap(),
  4774. domain = [],
  4775. range = [],
  4776. unknown = implicit;
  4777. function scale(d) {
  4778. let i = index.get(d);
  4779. if (i === undefined) {
  4780. if (unknown !== implicit) return unknown;
  4781. index.set(d, i = domain.push(d) - 1);
  4782. }
  4783. return range[i % range.length];
  4784. }
  4785. scale.domain = function(_) {
  4786. if (!arguments.length) return domain.slice();
  4787. domain = [], index = new InternMap();
  4788. for (const value of _) {
  4789. if (index.has(value)) continue;
  4790. index.set(value, domain.push(value) - 1);
  4791. }
  4792. return scale;
  4793. };
  4794. scale.range = function(_) {
  4795. return arguments.length ? (range = Array.from(_), scale) : range.slice();
  4796. };
  4797. scale.unknown = function(_) {
  4798. return arguments.length ? (unknown = _, scale) : unknown;
  4799. };
  4800. scale.copy = function() {
  4801. return ordinal(domain, range).unknown(unknown);
  4802. };
  4803. initRange.apply(scale, arguments);
  4804. return scale;
  4805. }
  4806. function colors(specifier) {
  4807. var n = specifier.length / 6 | 0, colors = new Array(n), i = 0;
  4808. while (i < n) colors[i] = "#" + specifier.slice(i * 6, ++i * 6);
  4809. return colors;
  4810. }
  4811. var schemePaired = colors("a6cee31f78b4b2df8a33a02cfb9a99e31a1cfdbf6fff7f00cab2d66a3d9affff99b15928");
  4812. var tinycolor = {exports: {}};
  4813. (function (module) {
  4814. // TinyColor v1.4.2
  4815. // https://github.com/bgrins/TinyColor
  4816. // Brian Grinstead, MIT License
  4817. (function(Math) {
  4818. var trimLeft = /^\s+/,
  4819. trimRight = /\s+$/,
  4820. tinyCounter = 0,
  4821. mathRound = Math.round,
  4822. mathMin = Math.min,
  4823. mathMax = Math.max,
  4824. mathRandom = Math.random;
  4825. function tinycolor (color, opts) {
  4826. color = (color) ? color : '';
  4827. opts = opts || { };
  4828. // If input is already a tinycolor, return itself
  4829. if (color instanceof tinycolor) {
  4830. return color;
  4831. }
  4832. // If we are called as a function, call using new instead
  4833. if (!(this instanceof tinycolor)) {
  4834. return new tinycolor(color, opts);
  4835. }
  4836. var rgb = inputToRGB(color);
  4837. this._originalInput = color,
  4838. this._r = rgb.r,
  4839. this._g = rgb.g,
  4840. this._b = rgb.b,
  4841. this._a = rgb.a,
  4842. this._roundA = mathRound(100*this._a) / 100,
  4843. this._format = opts.format || rgb.format;
  4844. this._gradientType = opts.gradientType;
  4845. // Don't let the range of [0,255] come back in [0,1].
  4846. // Potentially lose a little bit of precision here, but will fix issues where
  4847. // .5 gets interpreted as half of the total, instead of half of 1
  4848. // If it was supposed to be 128, this was already taken care of by `inputToRgb`
  4849. if (this._r < 1) { this._r = mathRound(this._r); }
  4850. if (this._g < 1) { this._g = mathRound(this._g); }
  4851. if (this._b < 1) { this._b = mathRound(this._b); }
  4852. this._ok = rgb.ok;
  4853. this._tc_id = tinyCounter++;
  4854. }
  4855. tinycolor.prototype = {
  4856. isDark: function() {
  4857. return this.getBrightness() < 128;
  4858. },
  4859. isLight: function() {
  4860. return !this.isDark();
  4861. },
  4862. isValid: function() {
  4863. return this._ok;
  4864. },
  4865. getOriginalInput: function() {
  4866. return this._originalInput;
  4867. },
  4868. getFormat: function() {
  4869. return this._format;
  4870. },
  4871. getAlpha: function() {
  4872. return this._a;
  4873. },
  4874. getBrightness: function() {
  4875. //http://www.w3.org/TR/AERT#color-contrast
  4876. var rgb = this.toRgb();
  4877. return (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000;
  4878. },
  4879. getLuminance: function() {
  4880. //http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
  4881. var rgb = this.toRgb();
  4882. var RsRGB, GsRGB, BsRGB, R, G, B;
  4883. RsRGB = rgb.r/255;
  4884. GsRGB = rgb.g/255;
  4885. BsRGB = rgb.b/255;
  4886. if (RsRGB <= 0.03928) {R = RsRGB / 12.92;} else {R = Math.pow(((RsRGB + 0.055) / 1.055), 2.4);}
  4887. if (GsRGB <= 0.03928) {G = GsRGB / 12.92;} else {G = Math.pow(((GsRGB + 0.055) / 1.055), 2.4);}
  4888. if (BsRGB <= 0.03928) {B = BsRGB / 12.92;} else {B = Math.pow(((BsRGB + 0.055) / 1.055), 2.4);}
  4889. return (0.2126 * R) + (0.7152 * G) + (0.0722 * B);
  4890. },
  4891. setAlpha: function(value) {
  4892. this._a = boundAlpha(value);
  4893. this._roundA = mathRound(100*this._a) / 100;
  4894. return this;
  4895. },
  4896. toHsv: function() {
  4897. var hsv = rgbToHsv(this._r, this._g, this._b);
  4898. return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: this._a };
  4899. },
  4900. toHsvString: function() {
  4901. var hsv = rgbToHsv(this._r, this._g, this._b);
  4902. var h = mathRound(hsv.h * 360), s = mathRound(hsv.s * 100), v = mathRound(hsv.v * 100);
  4903. return (this._a == 1) ?
  4904. "hsv(" + h + ", " + s + "%, " + v + "%)" :
  4905. "hsva(" + h + ", " + s + "%, " + v + "%, "+ this._roundA + ")";
  4906. },
  4907. toHsl: function() {
  4908. var hsl = rgbToHsl(this._r, this._g, this._b);
  4909. return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: this._a };
  4910. },
  4911. toHslString: function() {
  4912. var hsl = rgbToHsl(this._r, this._g, this._b);
  4913. var h = mathRound(hsl.h * 360), s = mathRound(hsl.s * 100), l = mathRound(hsl.l * 100);
  4914. return (this._a == 1) ?
  4915. "hsl(" + h + ", " + s + "%, " + l + "%)" :
  4916. "hsla(" + h + ", " + s + "%, " + l + "%, "+ this._roundA + ")";
  4917. },
  4918. toHex: function(allow3Char) {
  4919. return rgbToHex(this._r, this._g, this._b, allow3Char);
  4920. },
  4921. toHexString: function(allow3Char) {
  4922. return '#' + this.toHex(allow3Char);
  4923. },
  4924. toHex8: function(allow4Char) {
  4925. return rgbaToHex(this._r, this._g, this._b, this._a, allow4Char);
  4926. },
  4927. toHex8String: function(allow4Char) {
  4928. return '#' + this.toHex8(allow4Char);
  4929. },
  4930. toRgb: function() {
  4931. return { r: mathRound(this._r), g: mathRound(this._g), b: mathRound(this._b), a: this._a };
  4932. },
  4933. toRgbString: function() {
  4934. return (this._a == 1) ?
  4935. "rgb(" + mathRound(this._r) + ", " + mathRound(this._g) + ", " + mathRound(this._b) + ")" :
  4936. "rgba(" + mathRound(this._r) + ", " + mathRound(this._g) + ", " + mathRound(this._b) + ", " + this._roundA + ")";
  4937. },
  4938. toPercentageRgb: function() {
  4939. return { r: mathRound(bound01(this._r, 255) * 100) + "%", g: mathRound(bound01(this._g, 255) * 100) + "%", b: mathRound(bound01(this._b, 255) * 100) + "%", a: this._a };
  4940. },
  4941. toPercentageRgbString: function() {
  4942. return (this._a == 1) ?
  4943. "rgb(" + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%)" :
  4944. "rgba(" + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%, " + this._roundA + ")";
  4945. },
  4946. toName: function() {
  4947. if (this._a === 0) {
  4948. return "transparent";
  4949. }
  4950. if (this._a < 1) {
  4951. return false;
  4952. }
  4953. return hexNames[rgbToHex(this._r, this._g, this._b, true)] || false;
  4954. },
  4955. toFilter: function(secondColor) {
  4956. var hex8String = '#' + rgbaToArgbHex(this._r, this._g, this._b, this._a);
  4957. var secondHex8String = hex8String;
  4958. var gradientType = this._gradientType ? "GradientType = 1, " : "";
  4959. if (secondColor) {
  4960. var s = tinycolor(secondColor);
  4961. secondHex8String = '#' + rgbaToArgbHex(s._r, s._g, s._b, s._a);
  4962. }
  4963. return "progid:DXImageTransform.Microsoft.gradient("+gradientType+"startColorstr="+hex8String+",endColorstr="+secondHex8String+")";
  4964. },
  4965. toString: function(format) {
  4966. var formatSet = !!format;
  4967. format = format || this._format;
  4968. var formattedString = false;
  4969. var hasAlpha = this._a < 1 && this._a >= 0;
  4970. var needsAlphaFormat = !formatSet && hasAlpha && (format === "hex" || format === "hex6" || format === "hex3" || format === "hex4" || format === "hex8" || format === "name");
  4971. if (needsAlphaFormat) {
  4972. // Special case for "transparent", all other non-alpha formats
  4973. // will return rgba when there is transparency.
  4974. if (format === "name" && this._a === 0) {
  4975. return this.toName();
  4976. }
  4977. return this.toRgbString();
  4978. }
  4979. if (format === "rgb") {
  4980. formattedString = this.toRgbString();
  4981. }
  4982. if (format === "prgb") {
  4983. formattedString = this.toPercentageRgbString();
  4984. }
  4985. if (format === "hex" || format === "hex6") {
  4986. formattedString = this.toHexString();
  4987. }
  4988. if (format === "hex3") {
  4989. formattedString = this.toHexString(true);
  4990. }
  4991. if (format === "hex4") {
  4992. formattedString = this.toHex8String(true);
  4993. }
  4994. if (format === "hex8") {
  4995. formattedString = this.toHex8String();
  4996. }
  4997. if (format === "name") {
  4998. formattedString = this.toName();
  4999. }
  5000. if (format === "hsl") {
  5001. formattedString = this.toHslString();
  5002. }
  5003. if (format === "hsv") {
  5004. formattedString = this.toHsvString();
  5005. }
  5006. return formattedString || this.toHexString();
  5007. },
  5008. clone: function() {
  5009. return tinycolor(this.toString());
  5010. },
  5011. _applyModification: function(fn, args) {
  5012. var color = fn.apply(null, [this].concat([].slice.call(args)));
  5013. this._r = color._r;
  5014. this._g = color._g;
  5015. this._b = color._b;
  5016. this.setAlpha(color._a);
  5017. return this;
  5018. },
  5019. lighten: function() {
  5020. return this._applyModification(lighten, arguments);
  5021. },
  5022. brighten: function() {
  5023. return this._applyModification(brighten, arguments);
  5024. },
  5025. darken: function() {
  5026. return this._applyModification(darken, arguments);
  5027. },
  5028. desaturate: function() {
  5029. return this._applyModification(desaturate, arguments);
  5030. },
  5031. saturate: function() {
  5032. return this._applyModification(saturate, arguments);
  5033. },
  5034. greyscale: function() {
  5035. return this._applyModification(greyscale, arguments);
  5036. },
  5037. spin: function() {
  5038. return this._applyModification(spin, arguments);
  5039. },
  5040. _applyCombination: function(fn, args) {
  5041. return fn.apply(null, [this].concat([].slice.call(args)));
  5042. },
  5043. analogous: function() {
  5044. return this._applyCombination(analogous, arguments);
  5045. },
  5046. complement: function() {
  5047. return this._applyCombination(complement, arguments);
  5048. },
  5049. monochromatic: function() {
  5050. return this._applyCombination(monochromatic, arguments);
  5051. },
  5052. splitcomplement: function() {
  5053. return this._applyCombination(splitcomplement, arguments);
  5054. },
  5055. triad: function() {
  5056. return this._applyCombination(triad, arguments);
  5057. },
  5058. tetrad: function() {
  5059. return this._applyCombination(tetrad, arguments);
  5060. }
  5061. };
  5062. // If input is an object, force 1 into "1.0" to handle ratios properly
  5063. // String input requires "1.0" as input, so 1 will be treated as 1
  5064. tinycolor.fromRatio = function(color, opts) {
  5065. if (typeof color == "object") {
  5066. var newColor = {};
  5067. for (var i in color) {
  5068. if (color.hasOwnProperty(i)) {
  5069. if (i === "a") {
  5070. newColor[i] = color[i];
  5071. }
  5072. else {
  5073. newColor[i] = convertToPercentage(color[i]);
  5074. }
  5075. }
  5076. }
  5077. color = newColor;
  5078. }
  5079. return tinycolor(color, opts);
  5080. };
  5081. // Given a string or object, convert that input to RGB
  5082. // Possible string inputs:
  5083. //
  5084. // "red"
  5085. // "#f00" or "f00"
  5086. // "#ff0000" or "ff0000"
  5087. // "#ff000000" or "ff000000"
  5088. // "rgb 255 0 0" or "rgb (255, 0, 0)"
  5089. // "rgb 1.0 0 0" or "rgb (1, 0, 0)"
  5090. // "rgba (255, 0, 0, 1)" or "rgba 255, 0, 0, 1"
  5091. // "rgba (1.0, 0, 0, 1)" or "rgba 1.0, 0, 0, 1"
  5092. // "hsl(0, 100%, 50%)" or "hsl 0 100% 50%"
  5093. // "hsla(0, 100%, 50%, 1)" or "hsla 0 100% 50%, 1"
  5094. // "hsv(0, 100%, 100%)" or "hsv 0 100% 100%"
  5095. //
  5096. function inputToRGB(color) {
  5097. var rgb = { r: 0, g: 0, b: 0 };
  5098. var a = 1;
  5099. var s = null;
  5100. var v = null;
  5101. var l = null;
  5102. var ok = false;
  5103. var format = false;
  5104. if (typeof color == "string") {
  5105. color = stringInputToObject(color);
  5106. }
  5107. if (typeof color == "object") {
  5108. if (isValidCSSUnit(color.r) && isValidCSSUnit(color.g) && isValidCSSUnit(color.b)) {
  5109. rgb = rgbToRgb(color.r, color.g, color.b);
  5110. ok = true;
  5111. format = String(color.r).substr(-1) === "%" ? "prgb" : "rgb";
  5112. }
  5113. else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.v)) {
  5114. s = convertToPercentage(color.s);
  5115. v = convertToPercentage(color.v);
  5116. rgb = hsvToRgb(color.h, s, v);
  5117. ok = true;
  5118. format = "hsv";
  5119. }
  5120. else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.l)) {
  5121. s = convertToPercentage(color.s);
  5122. l = convertToPercentage(color.l);
  5123. rgb = hslToRgb(color.h, s, l);
  5124. ok = true;
  5125. format = "hsl";
  5126. }
  5127. if (color.hasOwnProperty("a")) {
  5128. a = color.a;
  5129. }
  5130. }
  5131. a = boundAlpha(a);
  5132. return {
  5133. ok: ok,
  5134. format: color.format || format,
  5135. r: mathMin(255, mathMax(rgb.r, 0)),
  5136. g: mathMin(255, mathMax(rgb.g, 0)),
  5137. b: mathMin(255, mathMax(rgb.b, 0)),
  5138. a: a
  5139. };
  5140. }
  5141. // Conversion Functions
  5142. // --------------------
  5143. // `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from:
  5144. // <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>
  5145. // `rgbToRgb`
  5146. // Handle bounds / percentage checking to conform to CSS color spec
  5147. // <http://www.w3.org/TR/css3-color/>
  5148. // *Assumes:* r, g, b in [0, 255] or [0, 1]
  5149. // *Returns:* { r, g, b } in [0, 255]
  5150. function rgbToRgb(r, g, b){
  5151. return {
  5152. r: bound01(r, 255) * 255,
  5153. g: bound01(g, 255) * 255,
  5154. b: bound01(b, 255) * 255
  5155. };
  5156. }
  5157. // `rgbToHsl`
  5158. // Converts an RGB color value to HSL.
  5159. // *Assumes:* r, g, and b are contained in [0, 255] or [0, 1]
  5160. // *Returns:* { h, s, l } in [0,1]
  5161. function rgbToHsl(r, g, b) {
  5162. r = bound01(r, 255);
  5163. g = bound01(g, 255);
  5164. b = bound01(b, 255);
  5165. var max = mathMax(r, g, b), min = mathMin(r, g, b);
  5166. var h, s, l = (max + min) / 2;
  5167. if(max == min) {
  5168. h = s = 0; // achromatic
  5169. }
  5170. else {
  5171. var d = max - min;
  5172. s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
  5173. switch(max) {
  5174. case r: h = (g - b) / d + (g < b ? 6 : 0); break;
  5175. case g: h = (b - r) / d + 2; break;
  5176. case b: h = (r - g) / d + 4; break;
  5177. }
  5178. h /= 6;
  5179. }
  5180. return { h: h, s: s, l: l };
  5181. }
  5182. // `hslToRgb`
  5183. // Converts an HSL color value to RGB.
  5184. // *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100]
  5185. // *Returns:* { r, g, b } in the set [0, 255]
  5186. function hslToRgb(h, s, l) {
  5187. var r, g, b;
  5188. h = bound01(h, 360);
  5189. s = bound01(s, 100);
  5190. l = bound01(l, 100);
  5191. function hue2rgb(p, q, t) {
  5192. if(t < 0) t += 1;
  5193. if(t > 1) t -= 1;
  5194. if(t < 1/6) return p + (q - p) * 6 * t;
  5195. if(t < 1/2) return q;
  5196. if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
  5197. return p;
  5198. }
  5199. if(s === 0) {
  5200. r = g = b = l; // achromatic
  5201. }
  5202. else {
  5203. var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
  5204. var p = 2 * l - q;
  5205. r = hue2rgb(p, q, h + 1/3);
  5206. g = hue2rgb(p, q, h);
  5207. b = hue2rgb(p, q, h - 1/3);
  5208. }
  5209. return { r: r * 255, g: g * 255, b: b * 255 };
  5210. }
  5211. // `rgbToHsv`
  5212. // Converts an RGB color value to HSV
  5213. // *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]
  5214. // *Returns:* { h, s, v } in [0,1]
  5215. function rgbToHsv(r, g, b) {
  5216. r = bound01(r, 255);
  5217. g = bound01(g, 255);
  5218. b = bound01(b, 255);
  5219. var max = mathMax(r, g, b), min = mathMin(r, g, b);
  5220. var h, s, v = max;
  5221. var d = max - min;
  5222. s = max === 0 ? 0 : d / max;
  5223. if(max == min) {
  5224. h = 0; // achromatic
  5225. }
  5226. else {
  5227. switch(max) {
  5228. case r: h = (g - b) / d + (g < b ? 6 : 0); break;
  5229. case g: h = (b - r) / d + 2; break;
  5230. case b: h = (r - g) / d + 4; break;
  5231. }
  5232. h /= 6;
  5233. }
  5234. return { h: h, s: s, v: v };
  5235. }
  5236. // `hsvToRgb`
  5237. // Converts an HSV color value to RGB.
  5238. // *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]
  5239. // *Returns:* { r, g, b } in the set [0, 255]
  5240. function hsvToRgb(h, s, v) {
  5241. h = bound01(h, 360) * 6;
  5242. s = bound01(s, 100);
  5243. v = bound01(v, 100);
  5244. var i = Math.floor(h),
  5245. f = h - i,
  5246. p = v * (1 - s),
  5247. q = v * (1 - f * s),
  5248. t = v * (1 - (1 - f) * s),
  5249. mod = i % 6,
  5250. r = [v, q, p, p, t, v][mod],
  5251. g = [t, v, v, q, p, p][mod],
  5252. b = [p, p, t, v, v, q][mod];
  5253. return { r: r * 255, g: g * 255, b: b * 255 };
  5254. }
  5255. // `rgbToHex`
  5256. // Converts an RGB color to hex
  5257. // Assumes r, g, and b are contained in the set [0, 255]
  5258. // Returns a 3 or 6 character hex
  5259. function rgbToHex(r, g, b, allow3Char) {
  5260. var hex = [
  5261. pad2(mathRound(r).toString(16)),
  5262. pad2(mathRound(g).toString(16)),
  5263. pad2(mathRound(b).toString(16))
  5264. ];
  5265. // Return a 3 character hex if possible
  5266. if (allow3Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1)) {
  5267. return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0);
  5268. }
  5269. return hex.join("");
  5270. }
  5271. // `rgbaToHex`
  5272. // Converts an RGBA color plus alpha transparency to hex
  5273. // Assumes r, g, b are contained in the set [0, 255] and
  5274. // a in [0, 1]. Returns a 4 or 8 character rgba hex
  5275. function rgbaToHex(r, g, b, a, allow4Char) {
  5276. var hex = [
  5277. pad2(mathRound(r).toString(16)),
  5278. pad2(mathRound(g).toString(16)),
  5279. pad2(mathRound(b).toString(16)),
  5280. pad2(convertDecimalToHex(a))
  5281. ];
  5282. // Return a 4 character hex if possible
  5283. if (allow4Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1) && hex[3].charAt(0) == hex[3].charAt(1)) {
  5284. return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0) + hex[3].charAt(0);
  5285. }
  5286. return hex.join("");
  5287. }
  5288. // `rgbaToArgbHex`
  5289. // Converts an RGBA color to an ARGB Hex8 string
  5290. // Rarely used, but required for "toFilter()"
  5291. function rgbaToArgbHex(r, g, b, a) {
  5292. var hex = [
  5293. pad2(convertDecimalToHex(a)),
  5294. pad2(mathRound(r).toString(16)),
  5295. pad2(mathRound(g).toString(16)),
  5296. pad2(mathRound(b).toString(16))
  5297. ];
  5298. return hex.join("");
  5299. }
  5300. // `equals`
  5301. // Can be called with any tinycolor input
  5302. tinycolor.equals = function (color1, color2) {
  5303. if (!color1 || !color2) { return false; }
  5304. return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString();
  5305. };
  5306. tinycolor.random = function() {
  5307. return tinycolor.fromRatio({
  5308. r: mathRandom(),
  5309. g: mathRandom(),
  5310. b: mathRandom()
  5311. });
  5312. };
  5313. // Modification Functions
  5314. // ----------------------
  5315. // Thanks to less.js for some of the basics here
  5316. // <https://github.com/cloudhead/less.js/blob/master/lib/less/functions.js>
  5317. function desaturate(color, amount) {
  5318. amount = (amount === 0) ? 0 : (amount || 10);
  5319. var hsl = tinycolor(color).toHsl();
  5320. hsl.s -= amount / 100;
  5321. hsl.s = clamp01(hsl.s);
  5322. return tinycolor(hsl);
  5323. }
  5324. function saturate(color, amount) {
  5325. amount = (amount === 0) ? 0 : (amount || 10);
  5326. var hsl = tinycolor(color).toHsl();
  5327. hsl.s += amount / 100;
  5328. hsl.s = clamp01(hsl.s);
  5329. return tinycolor(hsl);
  5330. }
  5331. function greyscale(color) {
  5332. return tinycolor(color).desaturate(100);
  5333. }
  5334. function lighten (color, amount) {
  5335. amount = (amount === 0) ? 0 : (amount || 10);
  5336. var hsl = tinycolor(color).toHsl();
  5337. hsl.l += amount / 100;
  5338. hsl.l = clamp01(hsl.l);
  5339. return tinycolor(hsl);
  5340. }
  5341. function brighten(color, amount) {
  5342. amount = (amount === 0) ? 0 : (amount || 10);
  5343. var rgb = tinycolor(color).toRgb();
  5344. rgb.r = mathMax(0, mathMin(255, rgb.r - mathRound(255 * - (amount / 100))));
  5345. rgb.g = mathMax(0, mathMin(255, rgb.g - mathRound(255 * - (amount / 100))));
  5346. rgb.b = mathMax(0, mathMin(255, rgb.b - mathRound(255 * - (amount / 100))));
  5347. return tinycolor(rgb);
  5348. }
  5349. function darken (color, amount) {
  5350. amount = (amount === 0) ? 0 : (amount || 10);
  5351. var hsl = tinycolor(color).toHsl();
  5352. hsl.l -= amount / 100;
  5353. hsl.l = clamp01(hsl.l);
  5354. return tinycolor(hsl);
  5355. }
  5356. // Spin takes a positive or negative amount within [-360, 360] indicating the change of hue.
  5357. // Values outside of this range will be wrapped into this range.
  5358. function spin(color, amount) {
  5359. var hsl = tinycolor(color).toHsl();
  5360. var hue = (hsl.h + amount) % 360;
  5361. hsl.h = hue < 0 ? 360 + hue : hue;
  5362. return tinycolor(hsl);
  5363. }
  5364. // Combination Functions
  5365. // ---------------------
  5366. // Thanks to jQuery xColor for some of the ideas behind these
  5367. // <https://github.com/infusion/jQuery-xcolor/blob/master/jquery.xcolor.js>
  5368. function complement(color) {
  5369. var hsl = tinycolor(color).toHsl();
  5370. hsl.h = (hsl.h + 180) % 360;
  5371. return tinycolor(hsl);
  5372. }
  5373. function triad(color) {
  5374. var hsl = tinycolor(color).toHsl();
  5375. var h = hsl.h;
  5376. return [
  5377. tinycolor(color),
  5378. tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }),
  5379. tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l })
  5380. ];
  5381. }
  5382. function tetrad(color) {
  5383. var hsl = tinycolor(color).toHsl();
  5384. var h = hsl.h;
  5385. return [
  5386. tinycolor(color),
  5387. tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }),
  5388. tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }),
  5389. tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l })
  5390. ];
  5391. }
  5392. function splitcomplement(color) {
  5393. var hsl = tinycolor(color).toHsl();
  5394. var h = hsl.h;
  5395. return [
  5396. tinycolor(color),
  5397. tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l}),
  5398. tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l})
  5399. ];
  5400. }
  5401. function analogous(color, results, slices) {
  5402. results = results || 6;
  5403. slices = slices || 30;
  5404. var hsl = tinycolor(color).toHsl();
  5405. var part = 360 / slices;
  5406. var ret = [tinycolor(color)];
  5407. for (hsl.h = ((hsl.h - (part * results >> 1)) + 720) % 360; --results; ) {
  5408. hsl.h = (hsl.h + part) % 360;
  5409. ret.push(tinycolor(hsl));
  5410. }
  5411. return ret;
  5412. }
  5413. function monochromatic(color, results) {
  5414. results = results || 6;
  5415. var hsv = tinycolor(color).toHsv();
  5416. var h = hsv.h, s = hsv.s, v = hsv.v;
  5417. var ret = [];
  5418. var modification = 1 / results;
  5419. while (results--) {
  5420. ret.push(tinycolor({ h: h, s: s, v: v}));
  5421. v = (v + modification) % 1;
  5422. }
  5423. return ret;
  5424. }
  5425. // Utility Functions
  5426. // ---------------------
  5427. tinycolor.mix = function(color1, color2, amount) {
  5428. amount = (amount === 0) ? 0 : (amount || 50);
  5429. var rgb1 = tinycolor(color1).toRgb();
  5430. var rgb2 = tinycolor(color2).toRgb();
  5431. var p = amount / 100;
  5432. var rgba = {
  5433. r: ((rgb2.r - rgb1.r) * p) + rgb1.r,
  5434. g: ((rgb2.g - rgb1.g) * p) + rgb1.g,
  5435. b: ((rgb2.b - rgb1.b) * p) + rgb1.b,
  5436. a: ((rgb2.a - rgb1.a) * p) + rgb1.a
  5437. };
  5438. return tinycolor(rgba);
  5439. };
  5440. // Readability Functions
  5441. // ---------------------
  5442. // <http://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef (WCAG Version 2)
  5443. // `contrast`
  5444. // Analyze the 2 colors and returns the color contrast defined by (WCAG Version 2)
  5445. tinycolor.readability = function(color1, color2) {
  5446. var c1 = tinycolor(color1);
  5447. var c2 = tinycolor(color2);
  5448. return (Math.max(c1.getLuminance(),c2.getLuminance())+0.05) / (Math.min(c1.getLuminance(),c2.getLuminance())+0.05);
  5449. };
  5450. // `isReadable`
  5451. // Ensure that foreground and background color combinations meet WCAG2 guidelines.
  5452. // The third argument is an optional Object.
  5453. // the 'level' property states 'AA' or 'AAA' - if missing or invalid, it defaults to 'AA';
  5454. // the 'size' property states 'large' or 'small' - if missing or invalid, it defaults to 'small'.
  5455. // If the entire object is absent, isReadable defaults to {level:"AA",size:"small"}.
  5456. // *Example*
  5457. // tinycolor.isReadable("#000", "#111") => false
  5458. // tinycolor.isReadable("#000", "#111",{level:"AA",size:"large"}) => false
  5459. tinycolor.isReadable = function(color1, color2, wcag2) {
  5460. var readability = tinycolor.readability(color1, color2);
  5461. var wcag2Parms, out;
  5462. out = false;
  5463. wcag2Parms = validateWCAG2Parms(wcag2);
  5464. switch (wcag2Parms.level + wcag2Parms.size) {
  5465. case "AAsmall":
  5466. case "AAAlarge":
  5467. out = readability >= 4.5;
  5468. break;
  5469. case "AAlarge":
  5470. out = readability >= 3;
  5471. break;
  5472. case "AAAsmall":
  5473. out = readability >= 7;
  5474. break;
  5475. }
  5476. return out;
  5477. };
  5478. // `mostReadable`
  5479. // Given a base color and a list of possible foreground or background
  5480. // colors for that base, returns the most readable color.
  5481. // Optionally returns Black or White if the most readable color is unreadable.
  5482. // *Example*
  5483. // tinycolor.mostReadable(tinycolor.mostReadable("#123", ["#124", "#125"],{includeFallbackColors:false}).toHexString(); // "#112255"
  5484. // tinycolor.mostReadable(tinycolor.mostReadable("#123", ["#124", "#125"],{includeFallbackColors:true}).toHexString(); // "#ffffff"
  5485. // tinycolor.mostReadable("#a8015a", ["#faf3f3"],{includeFallbackColors:true,level:"AAA",size:"large"}).toHexString(); // "#faf3f3"
  5486. // tinycolor.mostReadable("#a8015a", ["#faf3f3"],{includeFallbackColors:true,level:"AAA",size:"small"}).toHexString(); // "#ffffff"
  5487. tinycolor.mostReadable = function(baseColor, colorList, args) {
  5488. var bestColor = null;
  5489. var bestScore = 0;
  5490. var readability;
  5491. var includeFallbackColors, level, size ;
  5492. args = args || {};
  5493. includeFallbackColors = args.includeFallbackColors ;
  5494. level = args.level;
  5495. size = args.size;
  5496. for (var i= 0; i < colorList.length ; i++) {
  5497. readability = tinycolor.readability(baseColor, colorList[i]);
  5498. if (readability > bestScore) {
  5499. bestScore = readability;
  5500. bestColor = tinycolor(colorList[i]);
  5501. }
  5502. }
  5503. if (tinycolor.isReadable(baseColor, bestColor, {"level":level,"size":size}) || !includeFallbackColors) {
  5504. return bestColor;
  5505. }
  5506. else {
  5507. args.includeFallbackColors=false;
  5508. return tinycolor.mostReadable(baseColor,["#fff", "#000"],args);
  5509. }
  5510. };
  5511. // Big List of Colors
  5512. // ------------------
  5513. // <http://www.w3.org/TR/css3-color/#svg-color>
  5514. var names = tinycolor.names = {
  5515. aliceblue: "f0f8ff",
  5516. antiquewhite: "faebd7",
  5517. aqua: "0ff",
  5518. aquamarine: "7fffd4",
  5519. azure: "f0ffff",
  5520. beige: "f5f5dc",
  5521. bisque: "ffe4c4",
  5522. black: "000",
  5523. blanchedalmond: "ffebcd",
  5524. blue: "00f",
  5525. blueviolet: "8a2be2",
  5526. brown: "a52a2a",
  5527. burlywood: "deb887",
  5528. burntsienna: "ea7e5d",
  5529. cadetblue: "5f9ea0",
  5530. chartreuse: "7fff00",
  5531. chocolate: "d2691e",
  5532. coral: "ff7f50",
  5533. cornflowerblue: "6495ed",
  5534. cornsilk: "fff8dc",
  5535. crimson: "dc143c",
  5536. cyan: "0ff",
  5537. darkblue: "00008b",
  5538. darkcyan: "008b8b",
  5539. darkgoldenrod: "b8860b",
  5540. darkgray: "a9a9a9",
  5541. darkgreen: "006400",
  5542. darkgrey: "a9a9a9",
  5543. darkkhaki: "bdb76b",
  5544. darkmagenta: "8b008b",
  5545. darkolivegreen: "556b2f",
  5546. darkorange: "ff8c00",
  5547. darkorchid: "9932cc",
  5548. darkred: "8b0000",
  5549. darksalmon: "e9967a",
  5550. darkseagreen: "8fbc8f",
  5551. darkslateblue: "483d8b",
  5552. darkslategray: "2f4f4f",
  5553. darkslategrey: "2f4f4f",
  5554. darkturquoise: "00ced1",
  5555. darkviolet: "9400d3",
  5556. deeppink: "ff1493",
  5557. deepskyblue: "00bfff",
  5558. dimgray: "696969",
  5559. dimgrey: "696969",
  5560. dodgerblue: "1e90ff",
  5561. firebrick: "b22222",
  5562. floralwhite: "fffaf0",
  5563. forestgreen: "228b22",
  5564. fuchsia: "f0f",
  5565. gainsboro: "dcdcdc",
  5566. ghostwhite: "f8f8ff",
  5567. gold: "ffd700",
  5568. goldenrod: "daa520",
  5569. gray: "808080",
  5570. green: "008000",
  5571. greenyellow: "adff2f",
  5572. grey: "808080",
  5573. honeydew: "f0fff0",
  5574. hotpink: "ff69b4",
  5575. indianred: "cd5c5c",
  5576. indigo: "4b0082",
  5577. ivory: "fffff0",
  5578. khaki: "f0e68c",
  5579. lavender: "e6e6fa",
  5580. lavenderblush: "fff0f5",
  5581. lawngreen: "7cfc00",
  5582. lemonchiffon: "fffacd",
  5583. lightblue: "add8e6",
  5584. lightcoral: "f08080",
  5585. lightcyan: "e0ffff",
  5586. lightgoldenrodyellow: "fafad2",
  5587. lightgray: "d3d3d3",
  5588. lightgreen: "90ee90",
  5589. lightgrey: "d3d3d3",
  5590. lightpink: "ffb6c1",
  5591. lightsalmon: "ffa07a",
  5592. lightseagreen: "20b2aa",
  5593. lightskyblue: "87cefa",
  5594. lightslategray: "789",
  5595. lightslategrey: "789",
  5596. lightsteelblue: "b0c4de",
  5597. lightyellow: "ffffe0",
  5598. lime: "0f0",
  5599. limegreen: "32cd32",
  5600. linen: "faf0e6",
  5601. magenta: "f0f",
  5602. maroon: "800000",
  5603. mediumaquamarine: "66cdaa",
  5604. mediumblue: "0000cd",
  5605. mediumorchid: "ba55d3",
  5606. mediumpurple: "9370db",
  5607. mediumseagreen: "3cb371",
  5608. mediumslateblue: "7b68ee",
  5609. mediumspringgreen: "00fa9a",
  5610. mediumturquoise: "48d1cc",
  5611. mediumvioletred: "c71585",
  5612. midnightblue: "191970",
  5613. mintcream: "f5fffa",
  5614. mistyrose: "ffe4e1",
  5615. moccasin: "ffe4b5",
  5616. navajowhite: "ffdead",
  5617. navy: "000080",
  5618. oldlace: "fdf5e6",
  5619. olive: "808000",
  5620. olivedrab: "6b8e23",
  5621. orange: "ffa500",
  5622. orangered: "ff4500",
  5623. orchid: "da70d6",
  5624. palegoldenrod: "eee8aa",
  5625. palegreen: "98fb98",
  5626. paleturquoise: "afeeee",
  5627. palevioletred: "db7093",
  5628. papayawhip: "ffefd5",
  5629. peachpuff: "ffdab9",
  5630. peru: "cd853f",
  5631. pink: "ffc0cb",
  5632. plum: "dda0dd",
  5633. powderblue: "b0e0e6",
  5634. purple: "800080",
  5635. rebeccapurple: "663399",
  5636. red: "f00",
  5637. rosybrown: "bc8f8f",
  5638. royalblue: "4169e1",
  5639. saddlebrown: "8b4513",
  5640. salmon: "fa8072",
  5641. sandybrown: "f4a460",
  5642. seagreen: "2e8b57",
  5643. seashell: "fff5ee",
  5644. sienna: "a0522d",
  5645. silver: "c0c0c0",
  5646. skyblue: "87ceeb",
  5647. slateblue: "6a5acd",
  5648. slategray: "708090",
  5649. slategrey: "708090",
  5650. snow: "fffafa",
  5651. springgreen: "00ff7f",
  5652. steelblue: "4682b4",
  5653. tan: "d2b48c",
  5654. teal: "008080",
  5655. thistle: "d8bfd8",
  5656. tomato: "ff6347",
  5657. turquoise: "40e0d0",
  5658. violet: "ee82ee",
  5659. wheat: "f5deb3",
  5660. white: "fff",
  5661. whitesmoke: "f5f5f5",
  5662. yellow: "ff0",
  5663. yellowgreen: "9acd32"
  5664. };
  5665. // Make it easy to access colors via `hexNames[hex]`
  5666. var hexNames = tinycolor.hexNames = flip(names);
  5667. // Utilities
  5668. // ---------
  5669. // `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }`
  5670. function flip(o) {
  5671. var flipped = { };
  5672. for (var i in o) {
  5673. if (o.hasOwnProperty(i)) {
  5674. flipped[o[i]] = i;
  5675. }
  5676. }
  5677. return flipped;
  5678. }
  5679. // Return a valid alpha value [0,1] with all invalid values being set to 1
  5680. function boundAlpha(a) {
  5681. a = parseFloat(a);
  5682. if (isNaN(a) || a < 0 || a > 1) {
  5683. a = 1;
  5684. }
  5685. return a;
  5686. }
  5687. // Take input from [0, n] and return it as [0, 1]
  5688. function bound01(n, max) {
  5689. if (isOnePointZero(n)) { n = "100%"; }
  5690. var processPercent = isPercentage(n);
  5691. n = mathMin(max, mathMax(0, parseFloat(n)));
  5692. // Automatically convert percentage into number
  5693. if (processPercent) {
  5694. n = parseInt(n * max, 10) / 100;
  5695. }
  5696. // Handle floating point rounding errors
  5697. if ((Math.abs(n - max) < 0.000001)) {
  5698. return 1;
  5699. }
  5700. // Convert into [0, 1] range if it isn't already
  5701. return (n % max) / parseFloat(max);
  5702. }
  5703. // Force a number between 0 and 1
  5704. function clamp01(val) {
  5705. return mathMin(1, mathMax(0, val));
  5706. }
  5707. // Parse a base-16 hex value into a base-10 integer
  5708. function parseIntFromHex(val) {
  5709. return parseInt(val, 16);
  5710. }
  5711. // Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1
  5712. // <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0>
  5713. function isOnePointZero(n) {
  5714. return typeof n == "string" && n.indexOf('.') != -1 && parseFloat(n) === 1;
  5715. }
  5716. // Check to see if string passed in is a percentage
  5717. function isPercentage(n) {
  5718. return typeof n === "string" && n.indexOf('%') != -1;
  5719. }
  5720. // Force a hex value to have 2 characters
  5721. function pad2(c) {
  5722. return c.length == 1 ? '0' + c : '' + c;
  5723. }
  5724. // Replace a decimal with it's percentage value
  5725. function convertToPercentage(n) {
  5726. if (n <= 1) {
  5727. n = (n * 100) + "%";
  5728. }
  5729. return n;
  5730. }
  5731. // Converts a decimal to a hex value
  5732. function convertDecimalToHex(d) {
  5733. return Math.round(parseFloat(d) * 255).toString(16);
  5734. }
  5735. // Converts a hex value to a decimal
  5736. function convertHexToDecimal(h) {
  5737. return (parseIntFromHex(h) / 255);
  5738. }
  5739. var matchers = (function() {
  5740. // <http://www.w3.org/TR/css3-values/#integers>
  5741. var CSS_INTEGER = "[-\\+]?\\d+%?";
  5742. // <http://www.w3.org/TR/css3-values/#number-value>
  5743. var CSS_NUMBER = "[-\\+]?\\d*\\.\\d+%?";
  5744. // Allow positive/negative integer/number. Don't capture the either/or, just the entire outcome.
  5745. var CSS_UNIT = "(?:" + CSS_NUMBER + ")|(?:" + CSS_INTEGER + ")";
  5746. // Actual matching.
  5747. // Parentheses and commas are optional, but not required.
  5748. // Whitespace can take the place of commas or opening paren
  5749. var PERMISSIVE_MATCH3 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";
  5750. var PERMISSIVE_MATCH4 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";
  5751. return {
  5752. CSS_UNIT: new RegExp(CSS_UNIT),
  5753. rgb: new RegExp("rgb" + PERMISSIVE_MATCH3),
  5754. rgba: new RegExp("rgba" + PERMISSIVE_MATCH4),
  5755. hsl: new RegExp("hsl" + PERMISSIVE_MATCH3),
  5756. hsla: new RegExp("hsla" + PERMISSIVE_MATCH4),
  5757. hsv: new RegExp("hsv" + PERMISSIVE_MATCH3),
  5758. hsva: new RegExp("hsva" + PERMISSIVE_MATCH4),
  5759. hex3: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
  5760. hex6: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,
  5761. hex4: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
  5762. hex8: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/
  5763. };
  5764. })();
  5765. // `isValidCSSUnit`
  5766. // Take in a single string / number and check to see if it looks like a CSS unit
  5767. // (see `matchers` above for definition).
  5768. function isValidCSSUnit(color) {
  5769. return !!matchers.CSS_UNIT.exec(color);
  5770. }
  5771. // `stringInputToObject`
  5772. // Permissive string parsing. Take in a number of formats, and output an object
  5773. // based on detected format. Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}`
  5774. function stringInputToObject(color) {
  5775. color = color.replace(trimLeft,'').replace(trimRight, '').toLowerCase();
  5776. var named = false;
  5777. if (names[color]) {
  5778. color = names[color];
  5779. named = true;
  5780. }
  5781. else if (color == 'transparent') {
  5782. return { r: 0, g: 0, b: 0, a: 0, format: "name" };
  5783. }
  5784. // Try to match string input using regular expressions.
  5785. // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360]
  5786. // Just return an object and let the conversion functions handle that.
  5787. // This way the result will be the same whether the tinycolor is initialized with string or object.
  5788. var match;
  5789. if ((match = matchers.rgb.exec(color))) {
  5790. return { r: match[1], g: match[2], b: match[3] };
  5791. }
  5792. if ((match = matchers.rgba.exec(color))) {
  5793. return { r: match[1], g: match[2], b: match[3], a: match[4] };
  5794. }
  5795. if ((match = matchers.hsl.exec(color))) {
  5796. return { h: match[1], s: match[2], l: match[3] };
  5797. }
  5798. if ((match = matchers.hsla.exec(color))) {
  5799. return { h: match[1], s: match[2], l: match[3], a: match[4] };
  5800. }
  5801. if ((match = matchers.hsv.exec(color))) {
  5802. return { h: match[1], s: match[2], v: match[3] };
  5803. }
  5804. if ((match = matchers.hsva.exec(color))) {
  5805. return { h: match[1], s: match[2], v: match[3], a: match[4] };
  5806. }
  5807. if ((match = matchers.hex8.exec(color))) {
  5808. return {
  5809. r: parseIntFromHex(match[1]),
  5810. g: parseIntFromHex(match[2]),
  5811. b: parseIntFromHex(match[3]),
  5812. a: convertHexToDecimal(match[4]),
  5813. format: named ? "name" : "hex8"
  5814. };
  5815. }
  5816. if ((match = matchers.hex6.exec(color))) {
  5817. return {
  5818. r: parseIntFromHex(match[1]),
  5819. g: parseIntFromHex(match[2]),
  5820. b: parseIntFromHex(match[3]),
  5821. format: named ? "name" : "hex"
  5822. };
  5823. }
  5824. if ((match = matchers.hex4.exec(color))) {
  5825. return {
  5826. r: parseIntFromHex(match[1] + '' + match[1]),
  5827. g: parseIntFromHex(match[2] + '' + match[2]),
  5828. b: parseIntFromHex(match[3] + '' + match[3]),
  5829. a: convertHexToDecimal(match[4] + '' + match[4]),
  5830. format: named ? "name" : "hex8"
  5831. };
  5832. }
  5833. if ((match = matchers.hex3.exec(color))) {
  5834. return {
  5835. r: parseIntFromHex(match[1] + '' + match[1]),
  5836. g: parseIntFromHex(match[2] + '' + match[2]),
  5837. b: parseIntFromHex(match[3] + '' + match[3]),
  5838. format: named ? "name" : "hex"
  5839. };
  5840. }
  5841. return false;
  5842. }
  5843. function validateWCAG2Parms(parms) {
  5844. // return valid WCAG2 parms for isReadable.
  5845. // If input parms are invalid, return {"level":"AA", "size":"small"}
  5846. var level, size;
  5847. parms = parms || {"level":"AA", "size":"small"};
  5848. level = (parms.level || "AA").toUpperCase();
  5849. size = (parms.size || "small").toLowerCase();
  5850. if (level !== "AA" && level !== "AAA") {
  5851. level = "AA";
  5852. }
  5853. if (size !== "small" && size !== "large") {
  5854. size = "small";
  5855. }
  5856. return {"level":level, "size":size};
  5857. }
  5858. // Node: Export function
  5859. if (module.exports) {
  5860. module.exports = tinycolor;
  5861. }
  5862. // AMD/requirejs: Define the module
  5863. else {
  5864. window.tinycolor = tinycolor;
  5865. }
  5866. })(Math);
  5867. }(tinycolor));
  5868. var tinyColor = tinycolor.exports;
  5869. var colorStr2Hex = function colorStr2Hex(str) {
  5870. return isNaN(str) ? parseInt(tinyColor(str).toHex(), 16) : str;
  5871. };
  5872. var colorAlpha = function colorAlpha(str) {
  5873. return isNaN(str) ? tinyColor(str).getAlpha() : 1;
  5874. };
  5875. var autoColorScale = ordinal(schemePaired); // Autoset attribute colorField by colorByAccessor property
  5876. // If an object has already a color, don't set it
  5877. // Objects can be nodes or links
  5878. function autoColorObjects(objects, colorByAccessor, colorField) {
  5879. if (!colorByAccessor || typeof colorField !== 'string') return;
  5880. objects.filter(function (obj) {
  5881. return !obj[colorField];
  5882. }).forEach(function (obj) {
  5883. obj[colorField] = autoColorScale(colorByAccessor(obj));
  5884. });
  5885. }
  5886. function getDagDepths (_ref, idAccessor) {
  5887. var nodes = _ref.nodes,
  5888. links = _ref.links;
  5889. var _ref2 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},
  5890. _ref2$nodeFilter = _ref2.nodeFilter,
  5891. nodeFilter = _ref2$nodeFilter === void 0 ? function () {
  5892. return true;
  5893. } : _ref2$nodeFilter,
  5894. _ref2$onLoopError = _ref2.onLoopError,
  5895. onLoopError = _ref2$onLoopError === void 0 ? function (loopIds) {
  5896. throw "Invalid DAG structure! Found cycle in node path: ".concat(loopIds.join(' -> '), ".");
  5897. } : _ref2$onLoopError;
  5898. // linked graph
  5899. var graph = {};
  5900. nodes.forEach(function (node) {
  5901. return graph[idAccessor(node)] = {
  5902. data: node,
  5903. out: [],
  5904. depth: -1,
  5905. skip: !nodeFilter(node)
  5906. };
  5907. });
  5908. links.forEach(function (_ref3) {
  5909. var source = _ref3.source,
  5910. target = _ref3.target;
  5911. var sourceId = getNodeId(source);
  5912. var targetId = getNodeId(target);
  5913. if (!graph.hasOwnProperty(sourceId)) throw "Missing source node with id: ".concat(sourceId);
  5914. if (!graph.hasOwnProperty(targetId)) throw "Missing target node with id: ".concat(targetId);
  5915. var sourceNode = graph[sourceId];
  5916. var targetNode = graph[targetId];
  5917. sourceNode.out.push(targetNode);
  5918. function getNodeId(node) {
  5919. return _typeof(node) === 'object' ? idAccessor(node) : node;
  5920. }
  5921. });
  5922. var foundLoops = [];
  5923. traverse(Object.values(graph));
  5924. var nodeDepths = Object.assign.apply(Object, [{}].concat(_toConsumableArray$2(Object.entries(graph).filter(function (_ref4) {
  5925. var _ref5 = _slicedToArray$3(_ref4, 2),
  5926. node = _ref5[1];
  5927. return !node.skip;
  5928. }).map(function (_ref6) {
  5929. var _ref7 = _slicedToArray$3(_ref6, 2),
  5930. id = _ref7[0],
  5931. node = _ref7[1];
  5932. return _defineProperty$1({}, id, node.depth);
  5933. }))));
  5934. return nodeDepths;
  5935. function traverse(nodes) {
  5936. var nodeStack = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
  5937. var currentDepth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
  5938. for (var i = 0, l = nodes.length; i < l; i++) {
  5939. var node = nodes[i];
  5940. if (nodeStack.indexOf(node) !== -1) {
  5941. var _ret = function () {
  5942. var loop = [].concat(_toConsumableArray$2(nodeStack.slice(nodeStack.indexOf(node))), [node]).map(function (d) {
  5943. return idAccessor(d.data);
  5944. });
  5945. if (!foundLoops.some(function (foundLoop) {
  5946. return foundLoop.length === loop.length && foundLoop.every(function (id, idx) {
  5947. return id === loop[idx];
  5948. });
  5949. })) {
  5950. foundLoops.push(loop);
  5951. onLoopError(loop);
  5952. }
  5953. return "continue";
  5954. }();
  5955. if (_ret === "continue") continue;
  5956. }
  5957. if (currentDepth > node.depth) {
  5958. // Don't unnecessarily revisit chunks of the graph
  5959. node.depth = currentDepth;
  5960. traverse(node.out, [].concat(_toConsumableArray$2(nodeStack), [node]), currentDepth + (node.skip ? 0 : 1));
  5961. }
  5962. }
  5963. }
  5964. }
  5965. var three$1 = window.THREE ? window.THREE // Prefer consumption from global THREE, if exists
  5966. : {
  5967. Group: three$2.Group,
  5968. Mesh: three$2.Mesh,
  5969. MeshLambertMaterial: three$2.MeshLambertMaterial,
  5970. Color: three$2.Color,
  5971. BufferGeometry: three$2.BufferGeometry,
  5972. BufferAttribute: three$2.BufferAttribute,
  5973. Matrix4: three$2.Matrix4,
  5974. Vector3: three$2.Vector3,
  5975. SphereBufferGeometry: three$2.SphereBufferGeometry,
  5976. CylinderBufferGeometry: three$2.CylinderBufferGeometry,
  5977. TubeBufferGeometry: three$2.TubeBufferGeometry,
  5978. ConeBufferGeometry: three$2.ConeBufferGeometry,
  5979. Line: three$2.Line,
  5980. LineBasicMaterial: three$2.LineBasicMaterial,
  5981. QuadraticBezierCurve3: three$2.QuadraticBezierCurve3,
  5982. CubicBezierCurve3: three$2.CubicBezierCurve3,
  5983. Box3: three$2.Box3
  5984. };
  5985. var ngraph = {
  5986. graph: ngraph_graph,
  5987. forcelayout: forcelayout
  5988. };
  5989. var DAG_LEVEL_NODE_RATIO = 2; // support multiple method names for backwards threejs compatibility
  5990. var setAttributeFn = new three$1.BufferGeometry().setAttribute ? 'setAttribute' : 'addAttribute';
  5991. var applyMatrix4Fn = new three$1.BufferGeometry().applyMatrix4 ? 'applyMatrix4' : 'applyMatrix';
  5992. var ForceGraph = index$2({
  5993. props: {
  5994. jsonUrl: {
  5995. onChange: function onChange(jsonUrl, state) {
  5996. var _this = this;
  5997. if (jsonUrl && !state.fetchingJson) {
  5998. // Load data asynchronously
  5999. state.fetchingJson = true;
  6000. state.onLoading();
  6001. fetch(jsonUrl).then(function (r) {
  6002. return r.json();
  6003. }).then(function (json) {
  6004. state.fetchingJson = false;
  6005. state.onFinishLoading(json);
  6006. _this.graphData(json);
  6007. });
  6008. }
  6009. },
  6010. triggerUpdate: false
  6011. },
  6012. graphData: {
  6013. "default": {
  6014. nodes: [],
  6015. links: []
  6016. },
  6017. onChange: function onChange(graphData, state) {
  6018. state.engineRunning = false; // Pause simulation immediately
  6019. }
  6020. },
  6021. numDimensions: {
  6022. "default": 3,
  6023. onChange: function onChange(numDim, state) {
  6024. var chargeForce = state.d3ForceLayout.force('charge'); // Increase repulsion on 3D mode for improved spatial separation
  6025. if (chargeForce) {
  6026. chargeForce.strength(numDim > 2 ? -60 : -30);
  6027. }
  6028. if (numDim < 3) {
  6029. eraseDimension(state.graphData.nodes, 'z');
  6030. }
  6031. if (numDim < 2) {
  6032. eraseDimension(state.graphData.nodes, 'y');
  6033. }
  6034. function eraseDimension(nodes, dim) {
  6035. nodes.forEach(function (d) {
  6036. delete d[dim]; // position
  6037. delete d["v".concat(dim)]; // velocity
  6038. });
  6039. }
  6040. }
  6041. },
  6042. dagMode: {
  6043. onChange: function onChange(dagMode, state) {
  6044. // td, bu, lr, rl, zin, zout, radialin, radialout
  6045. !dagMode && state.forceEngine === 'd3' && (state.graphData.nodes || []).forEach(function (n) {
  6046. return n.fx = n.fy = n.fz = undefined;
  6047. }); // unfix nodes when disabling dag mode
  6048. }
  6049. },
  6050. dagLevelDistance: {},
  6051. dagNodeFilter: {
  6052. "default": function _default(node) {
  6053. return true;
  6054. }
  6055. },
  6056. onDagError: {
  6057. triggerUpdate: false
  6058. },
  6059. nodeRelSize: {
  6060. "default": 4
  6061. },
  6062. // volume per val unit
  6063. nodeId: {
  6064. "default": 'id'
  6065. },
  6066. nodeVal: {
  6067. "default": 'val'
  6068. },
  6069. nodeResolution: {
  6070. "default": 8
  6071. },
  6072. // how many slice segments in the sphere's circumference
  6073. nodeColor: {
  6074. "default": 'color'
  6075. },
  6076. nodeAutoColorBy: {},
  6077. nodeOpacity: {
  6078. "default": 0.75
  6079. },
  6080. nodeVisibility: {
  6081. "default": true
  6082. },
  6083. nodeThreeObject: {},
  6084. nodeThreeObjectExtend: {
  6085. "default": false
  6086. },
  6087. linkSource: {
  6088. "default": 'source'
  6089. },
  6090. linkTarget: {
  6091. "default": 'target'
  6092. },
  6093. linkVisibility: {
  6094. "default": true
  6095. },
  6096. linkColor: {
  6097. "default": 'color'
  6098. },
  6099. linkAutoColorBy: {},
  6100. linkOpacity: {
  6101. "default": 0.2
  6102. },
  6103. linkWidth: {},
  6104. // Rounded to nearest decimal. For falsy values use dimensionless line with 1px regardless of distance.
  6105. linkResolution: {
  6106. "default": 6
  6107. },
  6108. // how many radial segments in each line tube's geometry
  6109. linkCurvature: {
  6110. "default": 0,
  6111. triggerUpdate: false
  6112. },
  6113. // line curvature radius (0: straight, 1: semi-circle)
  6114. linkCurveRotation: {
  6115. "default": 0,
  6116. triggerUpdate: false
  6117. },
  6118. // line curve rotation along the line axis (0: interection with XY plane, PI: upside down)
  6119. linkMaterial: {},
  6120. linkThreeObject: {},
  6121. linkThreeObjectExtend: {
  6122. "default": false
  6123. },
  6124. linkPositionUpdate: {
  6125. triggerUpdate: false
  6126. },
  6127. // custom function to call for updating the link's position. Signature: (threeObj, { start: { x, y, z}, end: { x, y, z }}, link). If the function returns a truthy value, the regular link position update will not run.
  6128. linkDirectionalArrowLength: {
  6129. "default": 0
  6130. },
  6131. linkDirectionalArrowColor: {},
  6132. linkDirectionalArrowRelPos: {
  6133. "default": 0.5,
  6134. triggerUpdate: false
  6135. },
  6136. // value between 0<>1 indicating the relative pos along the (exposed) line
  6137. linkDirectionalArrowResolution: {
  6138. "default": 8
  6139. },
  6140. // how many slice segments in the arrow's conic circumference
  6141. linkDirectionalParticles: {
  6142. "default": 0
  6143. },
  6144. // animate photons travelling in the link direction
  6145. linkDirectionalParticleSpeed: {
  6146. "default": 0.01,
  6147. triggerUpdate: false
  6148. },
  6149. // in link length ratio per frame
  6150. linkDirectionalParticleWidth: {
  6151. "default": 0.5
  6152. },
  6153. linkDirectionalParticleColor: {},
  6154. linkDirectionalParticleResolution: {
  6155. "default": 4
  6156. },
  6157. // how many slice segments in the particle sphere's circumference
  6158. forceEngine: {
  6159. "default": 'd3'
  6160. },
  6161. // d3 or ngraph
  6162. d3AlphaMin: {
  6163. "default": 0
  6164. },
  6165. d3AlphaDecay: {
  6166. "default": 0.0228,
  6167. triggerUpdate: false,
  6168. onChange: function onChange(alphaDecay, state) {
  6169. state.d3ForceLayout.alphaDecay(alphaDecay);
  6170. }
  6171. },
  6172. d3AlphaTarget: {
  6173. "default": 0,
  6174. triggerUpdate: false,
  6175. onChange: function onChange(alphaTarget, state) {
  6176. state.d3ForceLayout.alphaTarget(alphaTarget);
  6177. }
  6178. },
  6179. d3VelocityDecay: {
  6180. "default": 0.4,
  6181. triggerUpdate: false,
  6182. onChange: function onChange(velocityDecay, state) {
  6183. state.d3ForceLayout.velocityDecay(velocityDecay);
  6184. }
  6185. },
  6186. ngraphPhysics: {
  6187. "default": {
  6188. // defaults from https://github.com/anvaka/ngraph.physics.simulator/blob/master/index.js
  6189. timeStep: 20,
  6190. gravity: -1.2,
  6191. theta: 0.8,
  6192. springLength: 30,
  6193. springCoefficient: 0.0008,
  6194. dragCoefficient: 0.02
  6195. }
  6196. },
  6197. warmupTicks: {
  6198. "default": 0,
  6199. triggerUpdate: false
  6200. },
  6201. // how many times to tick the force engine at init before starting to render
  6202. cooldownTicks: {
  6203. "default": Infinity,
  6204. triggerUpdate: false
  6205. },
  6206. cooldownTime: {
  6207. "default": 15000,
  6208. triggerUpdate: false
  6209. },
  6210. // ms
  6211. onLoading: {
  6212. "default": function _default() {},
  6213. triggerUpdate: false
  6214. },
  6215. onFinishLoading: {
  6216. "default": function _default() {},
  6217. triggerUpdate: false
  6218. },
  6219. onUpdate: {
  6220. "default": function _default() {},
  6221. triggerUpdate: false
  6222. },
  6223. onFinishUpdate: {
  6224. "default": function _default() {},
  6225. triggerUpdate: false
  6226. },
  6227. onEngineTick: {
  6228. "default": function _default() {},
  6229. triggerUpdate: false
  6230. },
  6231. onEngineStop: {
  6232. "default": function _default() {},
  6233. triggerUpdate: false
  6234. }
  6235. },
  6236. methods: {
  6237. refresh: function refresh(state) {
  6238. state._flushObjects = true;
  6239. state._rerender();
  6240. return this;
  6241. },
  6242. // Expose d3 forces for external manipulation
  6243. d3Force: function d3Force(state, forceName, forceFn) {
  6244. if (forceFn === undefined) {
  6245. return state.d3ForceLayout.force(forceName); // Force getter
  6246. }
  6247. state.d3ForceLayout.force(forceName, forceFn); // Force setter
  6248. return this;
  6249. },
  6250. d3ReheatSimulation: function d3ReheatSimulation(state) {
  6251. state.d3ForceLayout.alpha(1);
  6252. this.resetCountdown();
  6253. return this;
  6254. },
  6255. // reset cooldown state
  6256. resetCountdown: function resetCountdown(state) {
  6257. state.cntTicks = 0;
  6258. state.startTickTime = new Date();
  6259. state.engineRunning = true;
  6260. return this;
  6261. },
  6262. tickFrame: function tickFrame(state) {
  6263. var isD3Sim = state.forceEngine !== 'ngraph';
  6264. if (state.engineRunning) {
  6265. layoutTick();
  6266. }
  6267. updateArrows();
  6268. updatePhotons();
  6269. return this; //
  6270. function layoutTick() {
  6271. if (++state.cntTicks > state.cooldownTicks || new Date() - state.startTickTime > state.cooldownTime || isD3Sim && state.d3AlphaMin > 0 && state.d3ForceLayout.alpha() < state.d3AlphaMin) {
  6272. state.engineRunning = false; // Stop ticking graph
  6273. state.onEngineStop();
  6274. } else {
  6275. state.layout[isD3Sim ? 'tick' : 'step'](); // Tick it
  6276. state.onEngineTick();
  6277. } // Update nodes position
  6278. state.graphData.nodes.forEach(function (node) {
  6279. var obj = node.__threeObj;
  6280. if (!obj) return;
  6281. var pos = isD3Sim ? node : state.layout.getNodePosition(node[state.nodeId]);
  6282. obj.position.x = pos.x;
  6283. obj.position.y = pos.y || 0;
  6284. obj.position.z = pos.z || 0;
  6285. }); // Update links position
  6286. var linkWidthAccessor = index$1(state.linkWidth);
  6287. var linkCurvatureAccessor = index$1(state.linkCurvature);
  6288. var linkCurveRotationAccessor = index$1(state.linkCurveRotation);
  6289. var linkThreeObjectExtendAccessor = index$1(state.linkThreeObjectExtend);
  6290. state.graphData.links.forEach(function (link) {
  6291. var lineObj = link.__lineObj;
  6292. if (!lineObj) return;
  6293. var pos = isD3Sim ? link : state.layout.getLinkPosition(state.layout.graph.getLink(link.source, link.target).id);
  6294. var start = pos[isD3Sim ? 'source' : 'from'];
  6295. var end = pos[isD3Sim ? 'target' : 'to'];
  6296. if (!start || !end || !start.hasOwnProperty('x') || !end.hasOwnProperty('x')) return; // skip invalid link
  6297. calcLinkCurve(link); // calculate link curve for all links, including custom replaced, so it can be used in directional functionality
  6298. var extendedObj = linkThreeObjectExtendAccessor(link);
  6299. if (state.linkPositionUpdate && state.linkPositionUpdate(extendedObj ? lineObj.children[1] : lineObj, // pass child custom object if extending the default
  6300. {
  6301. start: {
  6302. x: start.x,
  6303. y: start.y,
  6304. z: start.z
  6305. },
  6306. end: {
  6307. x: end.x,
  6308. y: end.y,
  6309. z: end.z
  6310. }
  6311. }, link) && !extendedObj) {
  6312. // exit if successfully custom updated position of non-extended obj
  6313. return;
  6314. }
  6315. var curveResolution = 30; // # line segments
  6316. var curve = link.__curve; // select default line obj if it's an extended group
  6317. var line = lineObj.children.length ? lineObj.children[0] : lineObj;
  6318. if (line.type === 'Line') {
  6319. // Update line geometry
  6320. if (!curve) {
  6321. // straight line
  6322. var linePos = line.geometry.getAttribute('position');
  6323. if (!linePos || !linePos.array || linePos.array.length !== 6) {
  6324. line.geometry[setAttributeFn]('position', linePos = new three$1.BufferAttribute(new Float32Array(2 * 3), 3));
  6325. }
  6326. linePos.array[0] = start.x;
  6327. linePos.array[1] = start.y || 0;
  6328. linePos.array[2] = start.z || 0;
  6329. linePos.array[3] = end.x;
  6330. linePos.array[4] = end.y || 0;
  6331. linePos.array[5] = end.z || 0;
  6332. linePos.needsUpdate = true;
  6333. } else {
  6334. // bezier curve line
  6335. line.geometry.setFromPoints(curve.getPoints(curveResolution));
  6336. }
  6337. line.geometry.computeBoundingSphere();
  6338. } else if (line.type === 'Mesh') {
  6339. // Update cylinder geometry
  6340. if (!curve) {
  6341. // straight tube
  6342. if (!line.geometry.type.match(/^Cylinder(Buffer)?Geometry$/)) {
  6343. var linkWidth = Math.ceil(linkWidthAccessor(link) * 10) / 10;
  6344. var r = linkWidth / 2;
  6345. var geometry = new three$1.CylinderBufferGeometry(r, r, 1, state.linkResolution, 1, false);
  6346. geometry[applyMatrix4Fn](new three$1.Matrix4().makeTranslation(0, 1 / 2, 0));
  6347. geometry[applyMatrix4Fn](new three$1.Matrix4().makeRotationX(Math.PI / 2));
  6348. line.geometry.dispose();
  6349. line.geometry = geometry;
  6350. }
  6351. var vStart = new three$1.Vector3(start.x, start.y || 0, start.z || 0);
  6352. var vEnd = new three$1.Vector3(end.x, end.y || 0, end.z || 0);
  6353. var distance = vStart.distanceTo(vEnd);
  6354. line.position.x = vStart.x;
  6355. line.position.y = vStart.y;
  6356. line.position.z = vStart.z;
  6357. line.scale.z = distance;
  6358. line.parent.localToWorld(vEnd); // lookAt requires world coords
  6359. line.lookAt(vEnd);
  6360. } else {
  6361. // curved tube
  6362. if (!line.geometry.type.match(/^Tube(Buffer)?Geometry$/)) {
  6363. // reset object positioning
  6364. line.position.set(0, 0, 0);
  6365. line.rotation.set(0, 0, 0);
  6366. line.scale.set(1, 1, 1);
  6367. }
  6368. var _linkWidth = Math.ceil(linkWidthAccessor(link) * 10) / 10;
  6369. var _r = _linkWidth / 2;
  6370. var _geometry = new three$1.TubeBufferGeometry(curve, curveResolution, _r, state.linkResolution, false);
  6371. line.geometry.dispose();
  6372. line.geometry = _geometry;
  6373. }
  6374. }
  6375. }); //
  6376. function calcLinkCurve(link) {
  6377. var pos = isD3Sim ? link : state.layout.getLinkPosition(state.layout.graph.getLink(link.source, link.target).id);
  6378. var start = pos[isD3Sim ? 'source' : 'from'];
  6379. var end = pos[isD3Sim ? 'target' : 'to'];
  6380. if (!start || !end || !start.hasOwnProperty('x') || !end.hasOwnProperty('x')) return; // skip invalid link
  6381. var curvature = linkCurvatureAccessor(link);
  6382. if (!curvature) {
  6383. link.__curve = null; // Straight line
  6384. } else {
  6385. // bezier curve line (only for line types)
  6386. var vStart = new three$1.Vector3(start.x, start.y || 0, start.z || 0);
  6387. var vEnd = new three$1.Vector3(end.x, end.y || 0, end.z || 0);
  6388. var l = vStart.distanceTo(vEnd); // line length
  6389. var curve;
  6390. var curveRotation = linkCurveRotationAccessor(link);
  6391. if (l > 0) {
  6392. var dx = end.x - start.x;
  6393. var dy = end.y - start.y || 0;
  6394. var vLine = new three$1.Vector3().subVectors(vEnd, vStart);
  6395. var cp = vLine.clone().multiplyScalar(curvature).cross(dx !== 0 || dy !== 0 ? new three$1.Vector3(0, 0, 1) : new three$1.Vector3(0, 1, 0)) // avoid cross-product of parallel vectors (prefer Z, fallback to Y)
  6396. .applyAxisAngle(vLine.normalize(), curveRotation) // rotate along line axis according to linkCurveRotation
  6397. .add(new three$1.Vector3().addVectors(vStart, vEnd).divideScalar(2));
  6398. curve = new three$1.QuadraticBezierCurve3(vStart, cp, vEnd);
  6399. } else {
  6400. // Same point, draw a loop
  6401. var d = curvature * 70;
  6402. var endAngle = -curveRotation; // Rotate clockwise (from Z angle perspective)
  6403. var startAngle = endAngle + Math.PI / 2;
  6404. curve = new three$1.CubicBezierCurve3(vStart, new three$1.Vector3(d * Math.cos(startAngle), d * Math.sin(startAngle), 0).add(vStart), new three$1.Vector3(d * Math.cos(endAngle), d * Math.sin(endAngle), 0).add(vStart), vEnd);
  6405. }
  6406. link.__curve = curve;
  6407. }
  6408. }
  6409. }
  6410. function updateArrows() {
  6411. // update link arrow position
  6412. var arrowRelPosAccessor = index$1(state.linkDirectionalArrowRelPos);
  6413. var arrowLengthAccessor = index$1(state.linkDirectionalArrowLength);
  6414. var nodeValAccessor = index$1(state.nodeVal);
  6415. state.graphData.links.forEach(function (link) {
  6416. var arrowObj = link.__arrowObj;
  6417. if (!arrowObj) return;
  6418. var pos = isD3Sim ? link : state.layout.getLinkPosition(state.layout.graph.getLink(link.source, link.target).id);
  6419. var start = pos[isD3Sim ? 'source' : 'from'];
  6420. var end = pos[isD3Sim ? 'target' : 'to'];
  6421. if (!start || !end || !start.hasOwnProperty('x') || !end.hasOwnProperty('x')) return; // skip invalid link
  6422. var startR = Math.sqrt(Math.max(0, nodeValAccessor(start) || 1)) * state.nodeRelSize;
  6423. var endR = Math.sqrt(Math.max(0, nodeValAccessor(end) || 1)) * state.nodeRelSize;
  6424. var arrowLength = arrowLengthAccessor(link);
  6425. var arrowRelPos = arrowRelPosAccessor(link);
  6426. var getPosAlongLine = link.__curve ? function (t) {
  6427. return link.__curve.getPoint(t);
  6428. } // interpolate along bezier curve
  6429. : function (t) {
  6430. // straight line: interpolate linearly
  6431. var iplt = function iplt(dim, start, end, t) {
  6432. return start[dim] + (end[dim] - start[dim]) * t || 0;
  6433. };
  6434. return {
  6435. x: iplt('x', start, end, t),
  6436. y: iplt('y', start, end, t),
  6437. z: iplt('z', start, end, t)
  6438. };
  6439. };
  6440. var lineLen = link.__curve ? link.__curve.getLength() : Math.sqrt(['x', 'y', 'z'].map(function (dim) {
  6441. return Math.pow((end[dim] || 0) - (start[dim] || 0), 2);
  6442. }).reduce(function (acc, v) {
  6443. return acc + v;
  6444. }, 0));
  6445. var posAlongLine = startR + arrowLength + (lineLen - startR - endR - arrowLength) * arrowRelPos;
  6446. var arrowHead = getPosAlongLine(posAlongLine / lineLen);
  6447. var arrowTail = getPosAlongLine((posAlongLine - arrowLength) / lineLen);
  6448. ['x', 'y', 'z'].forEach(function (dim) {
  6449. return arrowObj.position[dim] = arrowTail[dim];
  6450. });
  6451. var headVec = _construct(three$1.Vector3, _toConsumableArray$2(['x', 'y', 'z'].map(function (c) {
  6452. return arrowHead[c];
  6453. })));
  6454. arrowObj.parent.localToWorld(headVec); // lookAt requires world coords
  6455. arrowObj.lookAt(headVec);
  6456. });
  6457. }
  6458. function updatePhotons() {
  6459. // update link particle positions
  6460. var particleSpeedAccessor = index$1(state.linkDirectionalParticleSpeed);
  6461. state.graphData.links.forEach(function (link) {
  6462. var cyclePhotons = link.__photonsObj && link.__photonsObj.children;
  6463. var singleHopPhotons = link.__singleHopPhotonsObj && link.__singleHopPhotonsObj.children;
  6464. if ((!singleHopPhotons || !singleHopPhotons.length) && (!cyclePhotons || !cyclePhotons.length)) return;
  6465. var pos = isD3Sim ? link : state.layout.getLinkPosition(state.layout.graph.getLink(link.source, link.target).id);
  6466. var start = pos[isD3Sim ? 'source' : 'from'];
  6467. var end = pos[isD3Sim ? 'target' : 'to'];
  6468. if (!start || !end || !start.hasOwnProperty('x') || !end.hasOwnProperty('x')) return; // skip invalid link
  6469. var particleSpeed = particleSpeedAccessor(link);
  6470. var getPhotonPos = link.__curve ? function (t) {
  6471. return link.__curve.getPoint(t);
  6472. } // interpolate along bezier curve
  6473. : function (t) {
  6474. // straight line: interpolate linearly
  6475. var iplt = function iplt(dim, start, end, t) {
  6476. return start[dim] + (end[dim] - start[dim]) * t || 0;
  6477. };
  6478. return {
  6479. x: iplt('x', start, end, t),
  6480. y: iplt('y', start, end, t),
  6481. z: iplt('z', start, end, t)
  6482. };
  6483. };
  6484. var photons = [].concat(_toConsumableArray$2(cyclePhotons || []), _toConsumableArray$2(singleHopPhotons || []));
  6485. photons.forEach(function (photon, idx) {
  6486. var singleHop = photon.parent.__linkThreeObjType === 'singleHopPhotons';
  6487. if (!photon.hasOwnProperty('__progressRatio')) {
  6488. photon.__progressRatio = singleHop ? 0 : idx / cyclePhotons.length;
  6489. }
  6490. photon.__progressRatio += particleSpeed;
  6491. if (photon.__progressRatio >= 1) {
  6492. if (!singleHop) {
  6493. photon.__progressRatio = photon.__progressRatio % 1;
  6494. } else {
  6495. // remove particle
  6496. photon.parent.remove(photon);
  6497. emptyObject(photon);
  6498. return;
  6499. }
  6500. }
  6501. var photonPosRatio = photon.__progressRatio;
  6502. var pos = getPhotonPos(photonPosRatio);
  6503. ['x', 'y', 'z'].forEach(function (dim) {
  6504. return photon.position[dim] = pos[dim];
  6505. });
  6506. });
  6507. });
  6508. }
  6509. },
  6510. emitParticle: function emitParticle(state, link) {
  6511. if (link) {
  6512. if (!link.__singleHopPhotonsObj) {
  6513. var obj = new three$1.Group();
  6514. obj.__linkThreeObjType = 'singleHopPhotons';
  6515. link.__singleHopPhotonsObj = obj;
  6516. state.graphScene.add(obj);
  6517. }
  6518. var particleWidthAccessor = index$1(state.linkDirectionalParticleWidth);
  6519. var photonR = Math.ceil(particleWidthAccessor(link) * 10) / 10 / 2;
  6520. var numSegments = state.linkDirectionalParticleResolution;
  6521. var particleGeometry = new three$1.SphereBufferGeometry(photonR, numSegments, numSegments);
  6522. var linkColorAccessor = index$1(state.linkColor);
  6523. var particleColorAccessor = index$1(state.linkDirectionalParticleColor);
  6524. var photonColor = particleColorAccessor(link) || linkColorAccessor(link) || '#f0f0f0';
  6525. var materialColor = new three$1.Color(colorStr2Hex(photonColor));
  6526. var opacity = state.linkOpacity * 3;
  6527. var particleMaterial = new three$1.MeshLambertMaterial({
  6528. color: materialColor,
  6529. transparent: true,
  6530. opacity: opacity
  6531. }); // add a single hop particle
  6532. link.__singleHopPhotonsObj.add(new three$1.Mesh(particleGeometry, particleMaterial));
  6533. }
  6534. return this;
  6535. },
  6536. getGraphBbox: function getGraphBbox(state) {
  6537. var nodeFilter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () {
  6538. return true;
  6539. };
  6540. if (!state.initialised) return null; // recursively collect all nested geometries bboxes
  6541. var bboxes = function getBboxes(obj) {
  6542. var bboxes = [];
  6543. if (obj.geometry) {
  6544. obj.geometry.computeBoundingBox();
  6545. var box = new three$1.Box3();
  6546. box.copy(obj.geometry.boundingBox).applyMatrix4(obj.matrixWorld);
  6547. bboxes.push(box);
  6548. }
  6549. return bboxes.concat.apply(bboxes, _toConsumableArray$2((obj.children || []).filter(function (obj) {
  6550. return !obj.hasOwnProperty('__graphObjType') || obj.__graphObjType === 'node' && nodeFilter(obj.__data);
  6551. } // exclude filtered out nodes
  6552. ).map(getBboxes)));
  6553. }(state.graphScene);
  6554. if (!bboxes.length) return null; // extract global x,y,z min/max
  6555. return Object.assign.apply(Object, _toConsumableArray$2(['x', 'y', 'z'].map(function (c) {
  6556. return _defineProperty$1({}, c, [min(bboxes, function (bb) {
  6557. return bb.min[c];
  6558. }), max(bboxes, function (bb) {
  6559. return bb.max[c];
  6560. })]);
  6561. })));
  6562. }
  6563. },
  6564. stateInit: function stateInit() {
  6565. return {
  6566. d3ForceLayout: d3ForceSimulation().force('link', d3ForceLink()).force('charge', d3ForceManyBody()).force('center', d3ForceCenter()).force('dagRadial', null).stop(),
  6567. engineRunning: false
  6568. };
  6569. },
  6570. init: function init(threeObj, state) {
  6571. // Main three object to manipulate
  6572. state.graphScene = threeObj;
  6573. },
  6574. update: function update(state, changedProps) {
  6575. var hasAnyPropChanged = function hasAnyPropChanged(propList) {
  6576. return propList.some(function (p) {
  6577. return changedProps.hasOwnProperty(p);
  6578. });
  6579. };
  6580. state.engineRunning = false; // pause simulation
  6581. state.onUpdate();
  6582. if (state.nodeAutoColorBy !== null && hasAnyPropChanged(['nodeAutoColorBy', 'graphData', 'nodeColor'])) {
  6583. // Auto add color to uncolored nodes
  6584. autoColorObjects(state.graphData.nodes, index$1(state.nodeAutoColorBy), state.nodeColor);
  6585. }
  6586. if (state.linkAutoColorBy !== null && hasAnyPropChanged(['linkAutoColorBy', 'graphData', 'linkColor'])) {
  6587. // Auto add color to uncolored links
  6588. autoColorObjects(state.graphData.links, index$1(state.linkAutoColorBy), state.linkColor);
  6589. } // Digest nodes WebGL objects
  6590. if (state._flushObjects || hasAnyPropChanged(['graphData', 'nodeThreeObject', 'nodeThreeObjectExtend', 'nodeVal', 'nodeColor', 'nodeVisibility', 'nodeRelSize', 'nodeResolution', 'nodeOpacity'])) {
  6591. var customObjectAccessor = index$1(state.nodeThreeObject);
  6592. var customObjectExtendAccessor = index$1(state.nodeThreeObjectExtend);
  6593. var valAccessor = index$1(state.nodeVal);
  6594. var colorAccessor = index$1(state.nodeColor);
  6595. var visibilityAccessor = index$1(state.nodeVisibility);
  6596. var sphereGeometries = {}; // indexed by node value
  6597. var sphereMaterials = {}; // indexed by color
  6598. threeDigest(state.graphData.nodes.filter(visibilityAccessor), state.graphScene, {
  6599. purge: state._flushObjects || hasAnyPropChanged([// recreate objects if any of these props have changed
  6600. 'nodeThreeObject', 'nodeThreeObjectExtend']),
  6601. objFilter: function objFilter(obj) {
  6602. return obj.__graphObjType === 'node';
  6603. },
  6604. createObj: function createObj(node) {
  6605. var customObj = customObjectAccessor(node);
  6606. var extendObj = customObjectExtendAccessor(node);
  6607. if (customObj && state.nodeThreeObject === customObj) {
  6608. // clone object if it's a shared object among all nodes
  6609. customObj = customObj.clone();
  6610. }
  6611. var obj;
  6612. if (customObj && !extendObj) {
  6613. obj = customObj;
  6614. } else {
  6615. // Add default object (sphere mesh)
  6616. obj = new three$1.Mesh();
  6617. obj.__graphDefaultObj = true;
  6618. if (customObj && extendObj) {
  6619. obj.add(customObj); // extend default with custom
  6620. }
  6621. }
  6622. obj.__graphObjType = 'node'; // Add object type
  6623. return obj;
  6624. },
  6625. updateObj: function updateObj(obj, node) {
  6626. if (obj.__graphDefaultObj) {
  6627. // bypass internal updates for custom node objects
  6628. var val = valAccessor(node) || 1;
  6629. var radius = Math.cbrt(val) * state.nodeRelSize;
  6630. var numSegments = state.nodeResolution;
  6631. if (!obj.geometry.type.match(/^Sphere(Buffer)?Geometry$/) || obj.geometry.parameters.radius !== radius || obj.geometry.parameters.widthSegments !== numSegments) {
  6632. if (!sphereGeometries.hasOwnProperty(val)) {
  6633. sphereGeometries[val] = new three$1.SphereBufferGeometry(radius, numSegments, numSegments);
  6634. }
  6635. obj.geometry.dispose();
  6636. obj.geometry = sphereGeometries[val];
  6637. }
  6638. var color = colorAccessor(node);
  6639. var materialColor = new three$1.Color(colorStr2Hex(color || '#ffffaa'));
  6640. var opacity = state.nodeOpacity * colorAlpha(color);
  6641. if (obj.material.type !== 'MeshLambertMaterial' || !obj.material.color.equals(materialColor) || obj.material.opacity !== opacity) {
  6642. if (!sphereMaterials.hasOwnProperty(color)) {
  6643. sphereMaterials[color] = new three$1.MeshLambertMaterial({
  6644. color: materialColor,
  6645. transparent: true,
  6646. opacity: opacity
  6647. });
  6648. }
  6649. obj.material.dispose();
  6650. obj.material = sphereMaterials[color];
  6651. }
  6652. }
  6653. }
  6654. });
  6655. } // Digest links WebGL objects
  6656. if (state._flushObjects || hasAnyPropChanged(['graphData', 'linkThreeObject', 'linkThreeObjectExtend', 'linkMaterial', 'linkColor', 'linkWidth', 'linkVisibility', 'linkResolution', 'linkOpacity', 'linkDirectionalArrowLength', 'linkDirectionalArrowColor', 'linkDirectionalArrowResolution', 'linkDirectionalParticles', 'linkDirectionalParticleWidth', 'linkDirectionalParticleColor', 'linkDirectionalParticleResolution'])) {
  6657. var _customObjectAccessor = index$1(state.linkThreeObject);
  6658. var _customObjectExtendAccessor = index$1(state.linkThreeObjectExtend);
  6659. var customMaterialAccessor = index$1(state.linkMaterial);
  6660. var _visibilityAccessor = index$1(state.linkVisibility);
  6661. var _colorAccessor = index$1(state.linkColor);
  6662. var widthAccessor = index$1(state.linkWidth);
  6663. var cylinderGeometries = {}; // indexed by link width
  6664. var lambertLineMaterials = {}; // for cylinder objects, indexed by link color
  6665. var basicLineMaterials = {}; // for line objects, indexed by link color
  6666. var visibleLinks = state.graphData.links.filter(_visibilityAccessor); // lines digest cycle
  6667. threeDigest(visibleLinks, state.graphScene, {
  6668. objBindAttr: '__lineObj',
  6669. purge: state._flushObjects || hasAnyPropChanged([// recreate objects if any of these props have changed
  6670. 'linkThreeObject', 'linkThreeObjectExtend', 'linkWidth']),
  6671. objFilter: function objFilter(obj) {
  6672. return obj.__graphObjType === 'link';
  6673. },
  6674. createObj: function createObj(link) {
  6675. var customObj = _customObjectAccessor(link);
  6676. var extendObj = _customObjectExtendAccessor(link);
  6677. if (customObj && state.linkThreeObject === customObj) {
  6678. // clone object if it's a shared object among all links
  6679. customObj = customObj.clone();
  6680. }
  6681. var defaultObj;
  6682. if (!customObj || extendObj) {
  6683. // construct default line obj
  6684. var useCylinder = !!widthAccessor(link);
  6685. if (useCylinder) {
  6686. defaultObj = new three$1.Mesh();
  6687. } else {
  6688. // Use plain line (constant width)
  6689. var lineGeometry = new three$1.BufferGeometry();
  6690. lineGeometry[setAttributeFn]('position', new three$1.BufferAttribute(new Float32Array(2 * 3), 3));
  6691. defaultObj = new three$1.Line(lineGeometry);
  6692. }
  6693. }
  6694. var obj;
  6695. if (!customObj) {
  6696. obj = defaultObj;
  6697. obj.__graphDefaultObj = true;
  6698. } else {
  6699. if (!extendObj) {
  6700. // use custom object
  6701. obj = customObj;
  6702. } else {
  6703. // extend default with custom in a group
  6704. obj = new three$1.Group();
  6705. obj.__graphDefaultObj = true;
  6706. obj.add(defaultObj);
  6707. obj.add(customObj);
  6708. }
  6709. }
  6710. obj.renderOrder = 10; // Prevent visual glitches of dark lines on top of nodes by rendering them last
  6711. obj.__graphObjType = 'link'; // Add object type
  6712. return obj;
  6713. },
  6714. updateObj: function updateObj(updObj, link) {
  6715. if (updObj.__graphDefaultObj) {
  6716. // bypass internal updates for custom link objects
  6717. // select default object if it's an extended group
  6718. var obj = updObj.children.length ? updObj.children[0] : updObj;
  6719. var linkWidth = Math.ceil(widthAccessor(link) * 10) / 10;
  6720. var useCylinder = !!linkWidth;
  6721. if (useCylinder) {
  6722. var r = linkWidth / 2;
  6723. var numSegments = state.linkResolution;
  6724. if (!obj.geometry.type.match(/^Cylinder(Buffer)?Geometry$/) || obj.geometry.parameters.radiusTop !== r || obj.geometry.parameters.radialSegments !== numSegments) {
  6725. if (!cylinderGeometries.hasOwnProperty(linkWidth)) {
  6726. var geometry = new three$1.CylinderBufferGeometry(r, r, 1, numSegments, 1, false);
  6727. geometry[applyMatrix4Fn](new three$1.Matrix4().makeTranslation(0, 1 / 2, 0));
  6728. geometry[applyMatrix4Fn](new three$1.Matrix4().makeRotationX(Math.PI / 2));
  6729. cylinderGeometries[linkWidth] = geometry;
  6730. }
  6731. obj.geometry.dispose();
  6732. obj.geometry = cylinderGeometries[linkWidth];
  6733. }
  6734. }
  6735. var customMaterial = customMaterialAccessor(link);
  6736. if (customMaterial) {
  6737. obj.material = customMaterial;
  6738. } else {
  6739. var color = _colorAccessor(link);
  6740. var materialColor = new three$1.Color(colorStr2Hex(color || '#f0f0f0'));
  6741. var opacity = state.linkOpacity * colorAlpha(color);
  6742. var materialType = useCylinder ? 'MeshLambertMaterial' : 'LineBasicMaterial';
  6743. if (obj.material.type !== materialType || !obj.material.color.equals(materialColor) || obj.material.opacity !== opacity) {
  6744. var lineMaterials = useCylinder ? lambertLineMaterials : basicLineMaterials;
  6745. if (!lineMaterials.hasOwnProperty(color)) {
  6746. lineMaterials[color] = new three$1[materialType]({
  6747. color: materialColor,
  6748. transparent: opacity < 1,
  6749. opacity: opacity,
  6750. depthWrite: opacity >= 1 // Prevent transparency issues
  6751. });
  6752. }
  6753. obj.material.dispose();
  6754. obj.material = lineMaterials[color];
  6755. }
  6756. }
  6757. }
  6758. }
  6759. }); // Arrows digest cycle
  6760. if (state.linkDirectionalArrowLength || changedProps.hasOwnProperty('linkDirectionalArrowLength')) {
  6761. var arrowLengthAccessor = index$1(state.linkDirectionalArrowLength);
  6762. var arrowColorAccessor = index$1(state.linkDirectionalArrowColor);
  6763. threeDigest(visibleLinks.filter(arrowLengthAccessor), state.graphScene, {
  6764. objBindAttr: '__arrowObj',
  6765. objFilter: function objFilter(obj) {
  6766. return obj.__linkThreeObjType === 'arrow';
  6767. },
  6768. createObj: function createObj() {
  6769. var obj = new three$1.Mesh(undefined, new three$1.MeshLambertMaterial({
  6770. transparent: true
  6771. }));
  6772. obj.__linkThreeObjType = 'arrow'; // Add object type
  6773. return obj;
  6774. },
  6775. updateObj: function updateObj(obj, link) {
  6776. var arrowLength = arrowLengthAccessor(link);
  6777. var numSegments = state.linkDirectionalArrowResolution;
  6778. if (!obj.geometry.type.match(/^Cone(Buffer)?Geometry$/) || obj.geometry.parameters.height !== arrowLength || obj.geometry.parameters.radialSegments !== numSegments) {
  6779. var coneGeometry = new three$1.ConeBufferGeometry(arrowLength * 0.25, arrowLength, numSegments); // Correct orientation
  6780. coneGeometry.translate(0, arrowLength / 2, 0);
  6781. coneGeometry.rotateX(Math.PI / 2);
  6782. obj.geometry.dispose();
  6783. obj.geometry = coneGeometry;
  6784. }
  6785. obj.material.color = new three$1.Color(arrowColorAccessor(link) || _colorAccessor(link) || '#f0f0f0');
  6786. obj.material.opacity = state.linkOpacity * 3;
  6787. }
  6788. });
  6789. } // Photon particles digest cycle
  6790. if (state.linkDirectionalParticles || changedProps.hasOwnProperty('linkDirectionalParticles')) {
  6791. var particlesAccessor = index$1(state.linkDirectionalParticles);
  6792. var particleWidthAccessor = index$1(state.linkDirectionalParticleWidth);
  6793. var particleColorAccessor = index$1(state.linkDirectionalParticleColor);
  6794. var particleMaterials = {}; // indexed by link color
  6795. var particleGeometries = {}; // indexed by particle width
  6796. threeDigest(visibleLinks.filter(particlesAccessor), state.graphScene, {
  6797. objBindAttr: '__photonsObj',
  6798. objFilter: function objFilter(obj) {
  6799. return obj.__linkThreeObjType === 'photons';
  6800. },
  6801. createObj: function createObj() {
  6802. var obj = new three$1.Group();
  6803. obj.__linkThreeObjType = 'photons'; // Add object type
  6804. return obj;
  6805. },
  6806. updateObj: function updateObj(obj, link) {
  6807. var numPhotons = Math.round(Math.abs(particlesAccessor(link)));
  6808. var curPhoton = !!obj.children.length && obj.children[0];
  6809. var photonR = Math.ceil(particleWidthAccessor(link) * 10) / 10 / 2;
  6810. var numSegments = state.linkDirectionalParticleResolution;
  6811. var particleGeometry;
  6812. if (curPhoton && curPhoton.geometry.parameters.radius === photonR && curPhoton.geometry.parameters.widthSegments === numSegments) {
  6813. particleGeometry = curPhoton.geometry;
  6814. } else {
  6815. if (!particleGeometries.hasOwnProperty(photonR)) {
  6816. particleGeometries[photonR] = new three$1.SphereBufferGeometry(photonR, numSegments, numSegments);
  6817. }
  6818. particleGeometry = particleGeometries[photonR];
  6819. curPhoton && curPhoton.geometry.dispose();
  6820. }
  6821. var photonColor = particleColorAccessor(link) || _colorAccessor(link) || '#f0f0f0';
  6822. var materialColor = new three$1.Color(colorStr2Hex(photonColor));
  6823. var opacity = state.linkOpacity * 3;
  6824. var particleMaterial;
  6825. if (curPhoton && curPhoton.material.color.equals(materialColor) && curPhoton.material.opacity === opacity) {
  6826. particleMaterial = curPhoton.material;
  6827. } else {
  6828. if (!particleMaterials.hasOwnProperty(photonColor)) {
  6829. particleMaterials[photonColor] = new three$1.MeshLambertMaterial({
  6830. color: materialColor,
  6831. transparent: true,
  6832. opacity: opacity
  6833. });
  6834. }
  6835. particleMaterial = particleMaterials[photonColor];
  6836. curPhoton && curPhoton.material.dispose();
  6837. } // digest cycle for each photon
  6838. threeDigest(_toConsumableArray$2(new Array(numPhotons)).map(function (_, idx) {
  6839. return {
  6840. idx: idx
  6841. };
  6842. }), obj, {
  6843. idAccessor: function idAccessor(d) {
  6844. return d.idx;
  6845. },
  6846. createObj: function createObj() {
  6847. return new three$1.Mesh(particleGeometry, particleMaterial);
  6848. },
  6849. updateObj: function updateObj(obj) {
  6850. obj.geometry = particleGeometry;
  6851. obj.material = particleMaterial;
  6852. }
  6853. });
  6854. }
  6855. });
  6856. }
  6857. }
  6858. state._flushObjects = false; // reset objects refresh flag
  6859. // simulation engine
  6860. if (hasAnyPropChanged(['graphData', 'nodeId', 'linkSource', 'linkTarget', 'numDimensions', 'forceEngine', 'dagMode', 'dagNodeFilter', 'dagLevelDistance'])) {
  6861. state.engineRunning = false; // Pause simulation
  6862. // parse links
  6863. state.graphData.links.forEach(function (link) {
  6864. link.source = link[state.linkSource];
  6865. link.target = link[state.linkTarget];
  6866. }); // Feed data to force-directed layout
  6867. var isD3Sim = state.forceEngine !== 'ngraph';
  6868. var layout;
  6869. if (isD3Sim) {
  6870. // D3-force
  6871. (layout = state.d3ForceLayout).stop().alpha(1) // re-heat the simulation
  6872. .numDimensions(state.numDimensions).nodes(state.graphData.nodes); // add links (if link force is still active)
  6873. var linkForce = state.d3ForceLayout.force('link');
  6874. if (linkForce) {
  6875. linkForce.id(function (d) {
  6876. return d[state.nodeId];
  6877. }).links(state.graphData.links);
  6878. } // setup dag force constraints
  6879. var nodeDepths = state.dagMode && getDagDepths(state.graphData, function (node) {
  6880. return node[state.nodeId];
  6881. }, {
  6882. nodeFilter: state.dagNodeFilter,
  6883. onLoopError: state.onDagError || undefined
  6884. });
  6885. var maxDepth = Math.max.apply(Math, _toConsumableArray$2(Object.values(nodeDepths || [])));
  6886. var dagLevelDistance = state.dagLevelDistance || state.graphData.nodes.length / (maxDepth || 1) * DAG_LEVEL_NODE_RATIO * (['radialin', 'radialout'].indexOf(state.dagMode) !== -1 ? 0.7 : 1); // Fix nodes to x,y,z for dag mode
  6887. if (state.dagMode) {
  6888. var getFFn = function getFFn(fix, invert) {
  6889. return function (node) {
  6890. return !fix ? undefined : (nodeDepths[node[state.nodeId]] - maxDepth / 2) * dagLevelDistance * (invert ? -1 : 1);
  6891. };
  6892. };
  6893. var fxFn = getFFn(['lr', 'rl'].indexOf(state.dagMode) !== -1, state.dagMode === 'rl');
  6894. var fyFn = getFFn(['td', 'bu'].indexOf(state.dagMode) !== -1, state.dagMode === 'td');
  6895. var fzFn = getFFn(['zin', 'zout'].indexOf(state.dagMode) !== -1, state.dagMode === 'zout');
  6896. state.graphData.nodes.filter(state.dagNodeFilter).forEach(function (node) {
  6897. node.fx = fxFn(node);
  6898. node.fy = fyFn(node);
  6899. node.fz = fzFn(node);
  6900. });
  6901. } // Use radial force for radial dags
  6902. state.d3ForceLayout.force('dagRadial', ['radialin', 'radialout'].indexOf(state.dagMode) !== -1 ? d3ForceRadial(function (node) {
  6903. var nodeDepth = nodeDepths[node[state.nodeId]] || -1;
  6904. return (state.dagMode === 'radialin' ? maxDepth - nodeDepth : nodeDepth) * dagLevelDistance;
  6905. }).strength(function (node) {
  6906. return state.dagNodeFilter(node) ? 1 : 0;
  6907. }) : null);
  6908. } else {
  6909. // ngraph
  6910. var _graph = ngraph.graph();
  6911. state.graphData.nodes.forEach(function (node) {
  6912. _graph.addNode(node[state.nodeId]);
  6913. });
  6914. state.graphData.links.forEach(function (link) {
  6915. _graph.addLink(link.source, link.target);
  6916. });
  6917. layout = ngraph.forcelayout(_graph, _objectSpread2$1({
  6918. dimensions: state.numDimensions
  6919. }, state.ngraphPhysics));
  6920. layout.graph = _graph; // Attach graph reference to layout
  6921. }
  6922. for (var i = 0; i < state.warmupTicks && !(isD3Sim && state.d3AlphaMin > 0 && state.d3ForceLayout.alpha() < state.d3AlphaMin); i++) {
  6923. layout[isD3Sim ? "tick" : "step"]();
  6924. } // Initial ticks before starting to render
  6925. state.layout = layout;
  6926. this.resetCountdown();
  6927. }
  6928. state.engineRunning = true; // resume simulation
  6929. state.onFinishUpdate();
  6930. }
  6931. });
  6932. function fromKapsule (kapsule) {
  6933. var baseClass = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Object;
  6934. var initKapsuleWithSelf = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
  6935. var FromKapsule = /*#__PURE__*/function (_baseClass) {
  6936. _inherits(FromKapsule, _baseClass);
  6937. var _super = _createSuper(FromKapsule);
  6938. function FromKapsule() {
  6939. var _this;
  6940. _classCallCheck$1(this, FromKapsule);
  6941. for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
  6942. args[_key] = arguments[_key];
  6943. }
  6944. _this = _super.call.apply(_super, [this].concat(args));
  6945. _this.__kapsuleInstance = kapsule().apply(void 0, [].concat(_toConsumableArray$2(initKapsuleWithSelf ? [_assertThisInitialized(_this)] : []), args));
  6946. return _this;
  6947. }
  6948. return FromKapsule;
  6949. }(baseClass); // attach kapsule props/methods to class prototype
  6950. Object.keys(kapsule()).forEach(function (m) {
  6951. return FromKapsule.prototype[m] = function () {
  6952. var _this$__kapsuleInstan;
  6953. var returnVal = (_this$__kapsuleInstan = this.__kapsuleInstance)[m].apply(_this$__kapsuleInstan, arguments);
  6954. return returnVal === this.__kapsuleInstance ? this // chain based on this class, not the kapsule obj
  6955. : returnVal;
  6956. };
  6957. });
  6958. return FromKapsule;
  6959. }
  6960. var three = window.THREE ? window.THREE : {
  6961. Group: three$2.Group
  6962. }; // Prefer consumption from global THREE, if exists
  6963. var threeForcegraph = fromKapsule(ForceGraph, three.Group, true);
  6964. return threeForcegraph;
  6965. })));
  6966. //# sourceMappingURL=three-forcegraph.js.map