123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659166601666116662166631666416665166661666716668166691667016671166721667316674166751667616677166781667916680166811668216683166841668516686166871668816689166901669116692166931669416695166961669716698166991670016701167021670316704167051670616707167081670916710167111671216713167141671516716167171671816719167201672116722167231672416725167261672716728167291673016731167321673316734167351673616737167381673916740167411674216743167441674516746167471674816749167501675116752167531675416755167561675716758167591676016761167621676316764167651676616767167681676916770167711677216773167741677516776167771677816779167801678116782167831678416785167861678716788167891679016791167921679316794167951679616797167981679916800168011680216803168041680516806168071680816809168101681116812168131681416815168161681716818168191682016821168221682316824168251682616827168281682916830168311683216833168341683516836168371683816839168401684116842168431684416845168461684716848168491685016851168521685316854168551685616857168581685916860168611686216863168641686516866168671686816869168701687116872168731687416875168761687716878168791688016881168821688316884168851688616887168881688916890168911689216893168941689516896168971689816899169001690116902169031690416905169061690716908169091691016911169121691316914169151691616917169181691916920169211692216923169241692516926169271692816929169301693116932169331693416935169361693716938169391694016941169421694316944169451694616947169481694916950169511695216953169541695516956169571695816959169601696116962169631696416965169661696716968169691697016971169721697316974169751697616977169781697916980169811698216983169841698516986169871698816989169901699116992169931699416995169961699716998169991700017001170021700317004170051700617007170081700917010170111701217013170141701517016170171701817019170201702117022170231702417025170261702717028170291703017031170321703317034170351703617037170381703917040170411704217043170441704517046170471704817049170501705117052170531705417055170561705717058170591706017061170621706317064170651706617067170681706917070170711707217073170741707517076170771707817079170801708117082170831708417085170861708717088170891709017091170921709317094170951709617097170981709917100171011710217103171041710517106171071710817109171101711117112171131711417115171161711717118171191712017121171221712317124171251712617127171281712917130171311713217133171341713517136171371713817139171401714117142171431714417145171461714717148171491715017151171521715317154171551715617157171581715917160 |
- /* This file is automatically rebuilt by the Cesium build process. */
- define(['exports', './when-e6985d2a', './Check-24cae389', './Math-392d0035', './Cartesian2-a5d6dde9', './RuntimeError-61701d3e'], function (exports, when, Check, _Math, Cartesian2, RuntimeError) { 'use strict';
- /**
- * A simple map projection where longitude and latitude are linearly mapped to X and Y by multiplying
- * them by the {@link Ellipsoid#maximumRadius}. This projection
- * is commonly known as geographic, equirectangular, equidistant cylindrical, or plate carrée. It
- * is also known as EPSG:4326.
- *
- * @alias GeographicProjection
- * @constructor
- *
- * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid.
- *
- * @see WebMercatorProjection
- */
- function GeographicProjection(ellipsoid) {
- this._ellipsoid = when.defaultValue(ellipsoid, Cartesian2.Ellipsoid.WGS84);
- this._semimajorAxis = this._ellipsoid.maximumRadius;
- this._oneOverSemimajorAxis = 1.0 / this._semimajorAxis;
- }
- Object.defineProperties(GeographicProjection.prototype, {
- /**
- * Gets the {@link Ellipsoid}.
- *
- * @memberof GeographicProjection.prototype
- *
- * @type {Ellipsoid}
- * @readonly
- */
- ellipsoid: {
- get: function () {
- return this._ellipsoid;
- },
- },
- });
- /**
- * Projects a set of {@link Cartographic} coordinates, in radians, to map coordinates, in meters.
- * X and Y are the longitude and latitude, respectively, multiplied by the maximum radius of the
- * ellipsoid. Z is the unmodified height.
- *
- * @param {Cartographic} cartographic The coordinates to project.
- * @param {Cartesian3} [result] An instance into which to copy the result. If this parameter is
- * undefined, a new instance is created and returned.
- * @returns {Cartesian3} The projected coordinates. If the result parameter is not undefined, the
- * coordinates are copied there and that instance is returned. Otherwise, a new instance is
- * created and returned.
- */
- GeographicProjection.prototype.project = function (cartographic, result) {
- // Actually this is the special case of equidistant cylindrical called the plate carree
- var semimajorAxis = this._semimajorAxis;
- var x = cartographic.longitude * semimajorAxis;
- var y = cartographic.latitude * semimajorAxis;
- var z = cartographic.height;
- if (!when.defined(result)) {
- return new Cartesian2.Cartesian3(x, y, z);
- }
- result.x = x;
- result.y = y;
- result.z = z;
- return result;
- };
- /**
- * Unprojects a set of projected {@link Cartesian3} coordinates, in meters, to {@link Cartographic}
- * coordinates, in radians. Longitude and Latitude are the X and Y coordinates, respectively,
- * divided by the maximum radius of the ellipsoid. Height is the unmodified Z coordinate.
- *
- * @param {Cartesian3} cartesian The Cartesian position to unproject with height (z) in meters.
- * @param {Cartographic} [result] An instance into which to copy the result. If this parameter is
- * undefined, a new instance is created and returned.
- * @returns {Cartographic} The unprojected coordinates. If the result parameter is not undefined, the
- * coordinates are copied there and that instance is returned. Otherwise, a new instance is
- * created and returned.
- */
- GeographicProjection.prototype.unproject = function (cartesian, result) {
- //>>includeStart('debug', pragmas.debug);
- if (!when.defined(cartesian)) {
- throw new Check.DeveloperError("cartesian is required");
- }
- //>>includeEnd('debug');
- var oneOverEarthSemimajorAxis = this._oneOverSemimajorAxis;
- var longitude = cartesian.x * oneOverEarthSemimajorAxis;
- var latitude = cartesian.y * oneOverEarthSemimajorAxis;
- var height = cartesian.z;
- if (!when.defined(result)) {
- return new Cartesian2.Cartographic(longitude, latitude, height);
- }
- result.longitude = longitude;
- result.latitude = latitude;
- result.height = height;
- return result;
- };
- /**
- * This enumerated type is used in determining where, relative to the frustum, an
- * object is located. The object can either be fully contained within the frustum (INSIDE),
- * partially inside the frustum and partially outside (INTERSECTING), or somewhere entirely
- * outside of the frustum's 6 planes (OUTSIDE).
- *
- * @enum {Number}
- */
- var Intersect = {
- /**
- * Represents that an object is not contained within the frustum.
- *
- * @type {Number}
- * @constant
- */
- OUTSIDE: -1,
- /**
- * Represents that an object intersects one of the frustum's planes.
- *
- * @type {Number}
- * @constant
- */
- INTERSECTING: 0,
- /**
- * Represents that an object is fully within the frustum.
- *
- * @type {Number}
- * @constant
- */
- INSIDE: 1,
- };
- var Intersect$1 = Object.freeze(Intersect);
- /**
- * Represents the closed interval [start, stop].
- * @alias Interval
- * @constructor
- *
- * @param {Number} [start=0.0] The beginning of the interval.
- * @param {Number} [stop=0.0] The end of the interval.
- */
- function Interval(start, stop) {
- /**
- * The beginning of the interval.
- * @type {Number}
- * @default 0.0
- */
- this.start = when.defaultValue(start, 0.0);
- /**
- * The end of the interval.
- * @type {Number}
- * @default 0.0
- */
- this.stop = when.defaultValue(stop, 0.0);
- }
- /**
- * A 3x3 matrix, indexable as a column-major order array.
- * Constructor parameters are in row-major order for code readability.
- * @alias Matrix3
- * @constructor
- * @implements {ArrayLike<number>}
- *
- * @param {Number} [column0Row0=0.0] The value for column 0, row 0.
- * @param {Number} [column1Row0=0.0] The value for column 1, row 0.
- * @param {Number} [column2Row0=0.0] The value for column 2, row 0.
- * @param {Number} [column0Row1=0.0] The value for column 0, row 1.
- * @param {Number} [column1Row1=0.0] The value for column 1, row 1.
- * @param {Number} [column2Row1=0.0] The value for column 2, row 1.
- * @param {Number} [column0Row2=0.0] The value for column 0, row 2.
- * @param {Number} [column1Row2=0.0] The value for column 1, row 2.
- * @param {Number} [column2Row2=0.0] The value for column 2, row 2.
- *
- * @see Matrix3.fromColumnMajorArray
- * @see Matrix3.fromRowMajorArray
- * @see Matrix3.fromQuaternion
- * @see Matrix3.fromScale
- * @see Matrix3.fromUniformScale
- * @see Matrix2
- * @see Matrix4
- */
- function Matrix3(
- column0Row0,
- column1Row0,
- column2Row0,
- column0Row1,
- column1Row1,
- column2Row1,
- column0Row2,
- column1Row2,
- column2Row2
- ) {
- this[0] = when.defaultValue(column0Row0, 0.0);
- this[1] = when.defaultValue(column0Row1, 0.0);
- this[2] = when.defaultValue(column0Row2, 0.0);
- this[3] = when.defaultValue(column1Row0, 0.0);
- this[4] = when.defaultValue(column1Row1, 0.0);
- this[5] = when.defaultValue(column1Row2, 0.0);
- this[6] = when.defaultValue(column2Row0, 0.0);
- this[7] = when.defaultValue(column2Row1, 0.0);
- this[8] = when.defaultValue(column2Row2, 0.0);
- }
- /**
- * The number of elements used to pack the object into an array.
- * @type {Number}
- */
- Matrix3.packedLength = 9;
- /**
- * Stores the provided instance into the provided array.
- *
- * @param {Matrix3} value The value to pack.
- * @param {Number[]} array The array to pack into.
- * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.
- *
- * @returns {Number[]} The array that was packed into
- */
- Matrix3.pack = function (value, array, startingIndex) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("value", value);
- Check.Check.defined("array", array);
- //>>includeEnd('debug');
- startingIndex = when.defaultValue(startingIndex, 0);
- array[startingIndex++] = value[0];
- array[startingIndex++] = value[1];
- array[startingIndex++] = value[2];
- array[startingIndex++] = value[3];
- array[startingIndex++] = value[4];
- array[startingIndex++] = value[5];
- array[startingIndex++] = value[6];
- array[startingIndex++] = value[7];
- array[startingIndex++] = value[8];
- return array;
- };
- /**
- * Retrieves an instance from a packed array.
- *
- * @param {Number[]} array The packed array.
- * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.
- * @param {Matrix3} [result] The object into which to store the result.
- * @returns {Matrix3} The modified result parameter or a new Matrix3 instance if one was not provided.
- */
- Matrix3.unpack = function (array, startingIndex, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.defined("array", array);
- //>>includeEnd('debug');
- startingIndex = when.defaultValue(startingIndex, 0);
- if (!when.defined(result)) {
- result = new Matrix3();
- }
- result[0] = array[startingIndex++];
- result[1] = array[startingIndex++];
- result[2] = array[startingIndex++];
- result[3] = array[startingIndex++];
- result[4] = array[startingIndex++];
- result[5] = array[startingIndex++];
- result[6] = array[startingIndex++];
- result[7] = array[startingIndex++];
- result[8] = array[startingIndex++];
- return result;
- };
- /**
- * Duplicates a Matrix3 instance.
- *
- * @param {Matrix3} matrix The matrix to duplicate.
- * @param {Matrix3} [result] The object onto which to store the result.
- * @returns {Matrix3} The modified result parameter or a new Matrix3 instance if one was not provided. (Returns undefined if matrix is undefined)
- */
- Matrix3.clone = function (matrix, result) {
- if (!when.defined(matrix)) {
- return undefined;
- }
- if (!when.defined(result)) {
- return new Matrix3(
- matrix[0],
- matrix[3],
- matrix[6],
- matrix[1],
- matrix[4],
- matrix[7],
- matrix[2],
- matrix[5],
- matrix[8]
- );
- }
- result[0] = matrix[0];
- result[1] = matrix[1];
- result[2] = matrix[2];
- result[3] = matrix[3];
- result[4] = matrix[4];
- result[5] = matrix[5];
- result[6] = matrix[6];
- result[7] = matrix[7];
- result[8] = matrix[8];
- return result;
- };
- /**
- * Creates a Matrix3 from 9 consecutive elements in an array.
- *
- * @param {Number[]} array The array whose 9 consecutive elements correspond to the positions of the matrix. Assumes column-major order.
- * @param {Number} [startingIndex=0] The offset into the array of the first element, which corresponds to first column first row position in the matrix.
- * @param {Matrix3} [result] The object onto which to store the result.
- * @returns {Matrix3} The modified result parameter or a new Matrix3 instance if one was not provided.
- *
- * @example
- * // Create the Matrix3:
- * // [1.0, 2.0, 3.0]
- * // [1.0, 2.0, 3.0]
- * // [1.0, 2.0, 3.0]
- *
- * var v = [1.0, 1.0, 1.0, 2.0, 2.0, 2.0, 3.0, 3.0, 3.0];
- * var m = Cesium.Matrix3.fromArray(v);
- *
- * // Create same Matrix3 with using an offset into an array
- * var v2 = [0.0, 0.0, 1.0, 1.0, 1.0, 2.0, 2.0, 2.0, 3.0, 3.0, 3.0];
- * var m2 = Cesium.Matrix3.fromArray(v2, 2);
- */
- Matrix3.fromArray = function (array, startingIndex, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.defined("array", array);
- //>>includeEnd('debug');
- startingIndex = when.defaultValue(startingIndex, 0);
- if (!when.defined(result)) {
- result = new Matrix3();
- }
- result[0] = array[startingIndex];
- result[1] = array[startingIndex + 1];
- result[2] = array[startingIndex + 2];
- result[3] = array[startingIndex + 3];
- result[4] = array[startingIndex + 4];
- result[5] = array[startingIndex + 5];
- result[6] = array[startingIndex + 6];
- result[7] = array[startingIndex + 7];
- result[8] = array[startingIndex + 8];
- return result;
- };
- /**
- * Creates a Matrix3 instance from a column-major order array.
- *
- * @param {Number[]} values The column-major order array.
- * @param {Matrix3} [result] The object in which the result will be stored, if undefined a new instance will be created.
- * @returns {Matrix3} The modified result parameter, or a new Matrix3 instance if one was not provided.
- */
- Matrix3.fromColumnMajorArray = function (values, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.defined("values", values);
- //>>includeEnd('debug');
- return Matrix3.clone(values, result);
- };
- /**
- * Creates a Matrix3 instance from a row-major order array.
- * The resulting matrix will be in column-major order.
- *
- * @param {Number[]} values The row-major order array.
- * @param {Matrix3} [result] The object in which the result will be stored, if undefined a new instance will be created.
- * @returns {Matrix3} The modified result parameter, or a new Matrix3 instance if one was not provided.
- */
- Matrix3.fromRowMajorArray = function (values, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.defined("values", values);
- //>>includeEnd('debug');
- if (!when.defined(result)) {
- return new Matrix3(
- values[0],
- values[1],
- values[2],
- values[3],
- values[4],
- values[5],
- values[6],
- values[7],
- values[8]
- );
- }
- result[0] = values[0];
- result[1] = values[3];
- result[2] = values[6];
- result[3] = values[1];
- result[4] = values[4];
- result[5] = values[7];
- result[6] = values[2];
- result[7] = values[5];
- result[8] = values[8];
- return result;
- };
- /**
- * Computes a 3x3 rotation matrix from the provided quaternion.
- *
- * @param {Quaternion} quaternion the quaternion to use.
- * @param {Matrix3} [result] The object in which the result will be stored, if undefined a new instance will be created.
- * @returns {Matrix3} The 3x3 rotation matrix from this quaternion.
- */
- Matrix3.fromQuaternion = function (quaternion, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("quaternion", quaternion);
- //>>includeEnd('debug');
- var x2 = quaternion.x * quaternion.x;
- var xy = quaternion.x * quaternion.y;
- var xz = quaternion.x * quaternion.z;
- var xw = quaternion.x * quaternion.w;
- var y2 = quaternion.y * quaternion.y;
- var yz = quaternion.y * quaternion.z;
- var yw = quaternion.y * quaternion.w;
- var z2 = quaternion.z * quaternion.z;
- var zw = quaternion.z * quaternion.w;
- var w2 = quaternion.w * quaternion.w;
- var m00 = x2 - y2 - z2 + w2;
- var m01 = 2.0 * (xy - zw);
- var m02 = 2.0 * (xz + yw);
- var m10 = 2.0 * (xy + zw);
- var m11 = -x2 + y2 - z2 + w2;
- var m12 = 2.0 * (yz - xw);
- var m20 = 2.0 * (xz - yw);
- var m21 = 2.0 * (yz + xw);
- var m22 = -x2 - y2 + z2 + w2;
- if (!when.defined(result)) {
- return new Matrix3(m00, m01, m02, m10, m11, m12, m20, m21, m22);
- }
- result[0] = m00;
- result[1] = m10;
- result[2] = m20;
- result[3] = m01;
- result[4] = m11;
- result[5] = m21;
- result[6] = m02;
- result[7] = m12;
- result[8] = m22;
- return result;
- };
- /**
- * Computes a 3x3 rotation matrix from the provided headingPitchRoll. (see http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles )
- *
- * @param {HeadingPitchRoll} headingPitchRoll the headingPitchRoll to use.
- * @param {Matrix3} [result] The object in which the result will be stored, if undefined a new instance will be created.
- * @returns {Matrix3} The 3x3 rotation matrix from this headingPitchRoll.
- */
- Matrix3.fromHeadingPitchRoll = function (headingPitchRoll, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("headingPitchRoll", headingPitchRoll);
- //>>includeEnd('debug');
- var cosTheta = Math.cos(-headingPitchRoll.pitch);
- var cosPsi = Math.cos(-headingPitchRoll.heading);
- var cosPhi = Math.cos(headingPitchRoll.roll);
- var sinTheta = Math.sin(-headingPitchRoll.pitch);
- var sinPsi = Math.sin(-headingPitchRoll.heading);
- var sinPhi = Math.sin(headingPitchRoll.roll);
- var m00 = cosTheta * cosPsi;
- var m01 = -cosPhi * sinPsi + sinPhi * sinTheta * cosPsi;
- var m02 = sinPhi * sinPsi + cosPhi * sinTheta * cosPsi;
- var m10 = cosTheta * sinPsi;
- var m11 = cosPhi * cosPsi + sinPhi * sinTheta * sinPsi;
- var m12 = -sinPhi * cosPsi + cosPhi * sinTheta * sinPsi;
- var m20 = -sinTheta;
- var m21 = sinPhi * cosTheta;
- var m22 = cosPhi * cosTheta;
- if (!when.defined(result)) {
- return new Matrix3(m00, m01, m02, m10, m11, m12, m20, m21, m22);
- }
- result[0] = m00;
- result[1] = m10;
- result[2] = m20;
- result[3] = m01;
- result[4] = m11;
- result[5] = m21;
- result[6] = m02;
- result[7] = m12;
- result[8] = m22;
- return result;
- };
- /**
- * Computes a Matrix3 instance representing a non-uniform scale.
- *
- * @param {Cartesian3} scale The x, y, and z scale factors.
- * @param {Matrix3} [result] The object in which the result will be stored, if undefined a new instance will be created.
- * @returns {Matrix3} The modified result parameter, or a new Matrix3 instance if one was not provided.
- *
- * @example
- * // Creates
- * // [7.0, 0.0, 0.0]
- * // [0.0, 8.0, 0.0]
- * // [0.0, 0.0, 9.0]
- * var m = Cesium.Matrix3.fromScale(new Cesium.Cartesian3(7.0, 8.0, 9.0));
- */
- Matrix3.fromScale = function (scale, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("scale", scale);
- //>>includeEnd('debug');
- if (!when.defined(result)) {
- return new Matrix3(scale.x, 0.0, 0.0, 0.0, scale.y, 0.0, 0.0, 0.0, scale.z);
- }
- result[0] = scale.x;
- result[1] = 0.0;
- result[2] = 0.0;
- result[3] = 0.0;
- result[4] = scale.y;
- result[5] = 0.0;
- result[6] = 0.0;
- result[7] = 0.0;
- result[8] = scale.z;
- return result;
- };
- /**
- * Computes a Matrix3 instance representing a uniform scale.
- *
- * @param {Number} scale The uniform scale factor.
- * @param {Matrix3} [result] The object in which the result will be stored, if undefined a new instance will be created.
- * @returns {Matrix3} The modified result parameter, or a new Matrix3 instance if one was not provided.
- *
- * @example
- * // Creates
- * // [2.0, 0.0, 0.0]
- * // [0.0, 2.0, 0.0]
- * // [0.0, 0.0, 2.0]
- * var m = Cesium.Matrix3.fromUniformScale(2.0);
- */
- Matrix3.fromUniformScale = function (scale, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.number("scale", scale);
- //>>includeEnd('debug');
- if (!when.defined(result)) {
- return new Matrix3(scale, 0.0, 0.0, 0.0, scale, 0.0, 0.0, 0.0, scale);
- }
- result[0] = scale;
- result[1] = 0.0;
- result[2] = 0.0;
- result[3] = 0.0;
- result[4] = scale;
- result[5] = 0.0;
- result[6] = 0.0;
- result[7] = 0.0;
- result[8] = scale;
- return result;
- };
- /**
- * Computes a Matrix3 instance representing the cross product equivalent matrix of a Cartesian3 vector.
- *
- * @param {Cartesian3} vector the vector on the left hand side of the cross product operation.
- * @param {Matrix3} [result] The object in which the result will be stored, if undefined a new instance will be created.
- * @returns {Matrix3} The modified result parameter, or a new Matrix3 instance if one was not provided.
- *
- * @example
- * // Creates
- * // [0.0, -9.0, 8.0]
- * // [9.0, 0.0, -7.0]
- * // [-8.0, 7.0, 0.0]
- * var m = Cesium.Matrix3.fromCrossProduct(new Cesium.Cartesian3(7.0, 8.0, 9.0));
- */
- Matrix3.fromCrossProduct = function (vector, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("vector", vector);
- //>>includeEnd('debug');
- if (!when.defined(result)) {
- return new Matrix3(
- 0.0,
- -vector.z,
- vector.y,
- vector.z,
- 0.0,
- -vector.x,
- -vector.y,
- vector.x,
- 0.0
- );
- }
- result[0] = 0.0;
- result[1] = vector.z;
- result[2] = -vector.y;
- result[3] = -vector.z;
- result[4] = 0.0;
- result[5] = vector.x;
- result[6] = vector.y;
- result[7] = -vector.x;
- result[8] = 0.0;
- return result;
- };
- /**
- * Creates a rotation matrix around the x-axis.
- *
- * @param {Number} angle The angle, in radians, of the rotation. Positive angles are counterclockwise.
- * @param {Matrix3} [result] The object in which the result will be stored, if undefined a new instance will be created.
- * @returns {Matrix3} The modified result parameter, or a new Matrix3 instance if one was not provided.
- *
- * @example
- * // Rotate a point 45 degrees counterclockwise around the x-axis.
- * var p = new Cesium.Cartesian3(5, 6, 7);
- * var m = Cesium.Matrix3.fromRotationX(Cesium.Math.toRadians(45.0));
- * var rotated = Cesium.Matrix3.multiplyByVector(m, p, new Cesium.Cartesian3());
- */
- Matrix3.fromRotationX = function (angle, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.number("angle", angle);
- //>>includeEnd('debug');
- var cosAngle = Math.cos(angle);
- var sinAngle = Math.sin(angle);
- if (!when.defined(result)) {
- return new Matrix3(
- 1.0,
- 0.0,
- 0.0,
- 0.0,
- cosAngle,
- -sinAngle,
- 0.0,
- sinAngle,
- cosAngle
- );
- }
- result[0] = 1.0;
- result[1] = 0.0;
- result[2] = 0.0;
- result[3] = 0.0;
- result[4] = cosAngle;
- result[5] = sinAngle;
- result[6] = 0.0;
- result[7] = -sinAngle;
- result[8] = cosAngle;
- return result;
- };
- /**
- * Creates a rotation matrix around the y-axis.
- *
- * @param {Number} angle The angle, in radians, of the rotation. Positive angles are counterclockwise.
- * @param {Matrix3} [result] The object in which the result will be stored, if undefined a new instance will be created.
- * @returns {Matrix3} The modified result parameter, or a new Matrix3 instance if one was not provided.
- *
- * @example
- * // Rotate a point 45 degrees counterclockwise around the y-axis.
- * var p = new Cesium.Cartesian3(5, 6, 7);
- * var m = Cesium.Matrix3.fromRotationY(Cesium.Math.toRadians(45.0));
- * var rotated = Cesium.Matrix3.multiplyByVector(m, p, new Cesium.Cartesian3());
- */
- Matrix3.fromRotationY = function (angle, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.number("angle", angle);
- //>>includeEnd('debug');
- var cosAngle = Math.cos(angle);
- var sinAngle = Math.sin(angle);
- if (!when.defined(result)) {
- return new Matrix3(
- cosAngle,
- 0.0,
- sinAngle,
- 0.0,
- 1.0,
- 0.0,
- -sinAngle,
- 0.0,
- cosAngle
- );
- }
- result[0] = cosAngle;
- result[1] = 0.0;
- result[2] = -sinAngle;
- result[3] = 0.0;
- result[4] = 1.0;
- result[5] = 0.0;
- result[6] = sinAngle;
- result[7] = 0.0;
- result[8] = cosAngle;
- return result;
- };
- /**
- * Creates a rotation matrix around the z-axis.
- *
- * @param {Number} angle The angle, in radians, of the rotation. Positive angles are counterclockwise.
- * @param {Matrix3} [result] The object in which the result will be stored, if undefined a new instance will be created.
- * @returns {Matrix3} The modified result parameter, or a new Matrix3 instance if one was not provided.
- *
- * @example
- * // Rotate a point 45 degrees counterclockwise around the z-axis.
- * var p = new Cesium.Cartesian3(5, 6, 7);
- * var m = Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(45.0));
- * var rotated = Cesium.Matrix3.multiplyByVector(m, p, new Cesium.Cartesian3());
- */
- Matrix3.fromRotationZ = function (angle, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.number("angle", angle);
- //>>includeEnd('debug');
- var cosAngle = Math.cos(angle);
- var sinAngle = Math.sin(angle);
- if (!when.defined(result)) {
- return new Matrix3(
- cosAngle,
- -sinAngle,
- 0.0,
- sinAngle,
- cosAngle,
- 0.0,
- 0.0,
- 0.0,
- 1.0
- );
- }
- result[0] = cosAngle;
- result[1] = sinAngle;
- result[2] = 0.0;
- result[3] = -sinAngle;
- result[4] = cosAngle;
- result[5] = 0.0;
- result[6] = 0.0;
- result[7] = 0.0;
- result[8] = 1.0;
- return result;
- };
- /**
- * Creates an Array from the provided Matrix3 instance.
- * The array will be in column-major order.
- *
- * @param {Matrix3} matrix The matrix to use..
- * @param {Number[]} [result] The Array onto which to store the result.
- * @returns {Number[]} The modified Array parameter or a new Array instance if one was not provided.
- */
- Matrix3.toArray = function (matrix, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- //>>includeEnd('debug');
- if (!when.defined(result)) {
- return [
- matrix[0],
- matrix[1],
- matrix[2],
- matrix[3],
- matrix[4],
- matrix[5],
- matrix[6],
- matrix[7],
- matrix[8],
- ];
- }
- result[0] = matrix[0];
- result[1] = matrix[1];
- result[2] = matrix[2];
- result[3] = matrix[3];
- result[4] = matrix[4];
- result[5] = matrix[5];
- result[6] = matrix[6];
- result[7] = matrix[7];
- result[8] = matrix[8];
- return result;
- };
- /**
- * Computes the array index of the element at the provided row and column.
- *
- * @param {Number} row The zero-based index of the row.
- * @param {Number} column The zero-based index of the column.
- * @returns {Number} The index of the element at the provided row and column.
- *
- * @exception {DeveloperError} row must be 0, 1, or 2.
- * @exception {DeveloperError} column must be 0, 1, or 2.
- *
- * @example
- * var myMatrix = new Cesium.Matrix3();
- * var column1Row0Index = Cesium.Matrix3.getElementIndex(1, 0);
- * var column1Row0 = myMatrix[column1Row0Index]
- * myMatrix[column1Row0Index] = 10.0;
- */
- Matrix3.getElementIndex = function (column, row) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.number.greaterThanOrEquals("row", row, 0);
- Check.Check.typeOf.number.lessThanOrEquals("row", row, 2);
- Check.Check.typeOf.number.greaterThanOrEquals("column", column, 0);
- Check.Check.typeOf.number.lessThanOrEquals("column", column, 2);
- //>>includeEnd('debug');
- return column * 3 + row;
- };
- /**
- * Retrieves a copy of the matrix column at the provided index as a Cartesian3 instance.
- *
- * @param {Matrix3} matrix The matrix to use.
- * @param {Number} index The zero-based index of the column to retrieve.
- * @param {Cartesian3} result The object onto which to store the result.
- * @returns {Cartesian3} The modified result parameter.
- *
- * @exception {DeveloperError} index must be 0, 1, or 2.
- */
- Matrix3.getColumn = function (matrix, index, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- Check.Check.typeOf.number.greaterThanOrEquals("index", index, 0);
- Check.Check.typeOf.number.lessThanOrEquals("index", index, 2);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- var startIndex = index * 3;
- var x = matrix[startIndex];
- var y = matrix[startIndex + 1];
- var z = matrix[startIndex + 2];
- result.x = x;
- result.y = y;
- result.z = z;
- return result;
- };
- /**
- * Computes a new matrix that replaces the specified column in the provided matrix with the provided Cartesian3 instance.
- *
- * @param {Matrix3} matrix The matrix to use.
- * @param {Number} index The zero-based index of the column to set.
- * @param {Cartesian3} cartesian The Cartesian whose values will be assigned to the specified column.
- * @param {Matrix3} result The object onto which to store the result.
- * @returns {Matrix3} The modified result parameter.
- *
- * @exception {DeveloperError} index must be 0, 1, or 2.
- */
- Matrix3.setColumn = function (matrix, index, cartesian, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- Check.Check.typeOf.number.greaterThanOrEquals("index", index, 0);
- Check.Check.typeOf.number.lessThanOrEquals("index", index, 2);
- Check.Check.typeOf.object("cartesian", cartesian);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- result = Matrix3.clone(matrix, result);
- var startIndex = index * 3;
- result[startIndex] = cartesian.x;
- result[startIndex + 1] = cartesian.y;
- result[startIndex + 2] = cartesian.z;
- return result;
- };
- /**
- * Retrieves a copy of the matrix row at the provided index as a Cartesian3 instance.
- *
- * @param {Matrix3} matrix The matrix to use.
- * @param {Number} index The zero-based index of the row to retrieve.
- * @param {Cartesian3} result The object onto which to store the result.
- * @returns {Cartesian3} The modified result parameter.
- *
- * @exception {DeveloperError} index must be 0, 1, or 2.
- */
- Matrix3.getRow = function (matrix, index, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- Check.Check.typeOf.number.greaterThanOrEquals("index", index, 0);
- Check.Check.typeOf.number.lessThanOrEquals("index", index, 2);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- var x = matrix[index];
- var y = matrix[index + 3];
- var z = matrix[index + 6];
- result.x = x;
- result.y = y;
- result.z = z;
- return result;
- };
- /**
- * Computes a new matrix that replaces the specified row in the provided matrix with the provided Cartesian3 instance.
- *
- * @param {Matrix3} matrix The matrix to use.
- * @param {Number} index The zero-based index of the row to set.
- * @param {Cartesian3} cartesian The Cartesian whose values will be assigned to the specified row.
- * @param {Matrix3} result The object onto which to store the result.
- * @returns {Matrix3} The modified result parameter.
- *
- * @exception {DeveloperError} index must be 0, 1, or 2.
- */
- Matrix3.setRow = function (matrix, index, cartesian, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- Check.Check.typeOf.number.greaterThanOrEquals("index", index, 0);
- Check.Check.typeOf.number.lessThanOrEquals("index", index, 2);
- Check.Check.typeOf.object("cartesian", cartesian);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- result = Matrix3.clone(matrix, result);
- result[index] = cartesian.x;
- result[index + 3] = cartesian.y;
- result[index + 6] = cartesian.z;
- return result;
- };
- var scratchColumn = new Cartesian2.Cartesian3();
- /**
- * Extracts the non-uniform scale assuming the matrix is an affine transformation.
- *
- * @param {Matrix3} matrix The matrix.
- * @param {Cartesian3} result The object onto which to store the result.
- * @returns {Cartesian3} The modified result parameter.
- */
- Matrix3.getScale = function (matrix, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- result.x = Cartesian2.Cartesian3.magnitude(
- Cartesian2.Cartesian3.fromElements(matrix[0], matrix[1], matrix[2], scratchColumn)
- );
- result.y = Cartesian2.Cartesian3.magnitude(
- Cartesian2.Cartesian3.fromElements(matrix[3], matrix[4], matrix[5], scratchColumn)
- );
- result.z = Cartesian2.Cartesian3.magnitude(
- Cartesian2.Cartesian3.fromElements(matrix[6], matrix[7], matrix[8], scratchColumn)
- );
- return result;
- };
- var scratchScale = new Cartesian2.Cartesian3();
- /**
- * Computes the maximum scale assuming the matrix is an affine transformation.
- * The maximum scale is the maximum length of the column vectors.
- *
- * @param {Matrix3} matrix The matrix.
- * @returns {Number} The maximum scale.
- */
- Matrix3.getMaximumScale = function (matrix) {
- Matrix3.getScale(matrix, scratchScale);
- return Cartesian2.Cartesian3.maximumComponent(scratchScale);
- };
- /**
- * Computes the product of two matrices.
- *
- * @param {Matrix3} left The first matrix.
- * @param {Matrix3} right The second matrix.
- * @param {Matrix3} result The object onto which to store the result.
- * @returns {Matrix3} The modified result parameter.
- */
- Matrix3.multiply = function (left, right, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("left", left);
- Check.Check.typeOf.object("right", right);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- var column0Row0 =
- left[0] * right[0] + left[3] * right[1] + left[6] * right[2];
- var column0Row1 =
- left[1] * right[0] + left[4] * right[1] + left[7] * right[2];
- var column0Row2 =
- left[2] * right[0] + left[5] * right[1] + left[8] * right[2];
- var column1Row0 =
- left[0] * right[3] + left[3] * right[4] + left[6] * right[5];
- var column1Row1 =
- left[1] * right[3] + left[4] * right[4] + left[7] * right[5];
- var column1Row2 =
- left[2] * right[3] + left[5] * right[4] + left[8] * right[5];
- var column2Row0 =
- left[0] * right[6] + left[3] * right[7] + left[6] * right[8];
- var column2Row1 =
- left[1] * right[6] + left[4] * right[7] + left[7] * right[8];
- var column2Row2 =
- left[2] * right[6] + left[5] * right[7] + left[8] * right[8];
- result[0] = column0Row0;
- result[1] = column0Row1;
- result[2] = column0Row2;
- result[3] = column1Row0;
- result[4] = column1Row1;
- result[5] = column1Row2;
- result[6] = column2Row0;
- result[7] = column2Row1;
- result[8] = column2Row2;
- return result;
- };
- /**
- * Computes the sum of two matrices.
- *
- * @param {Matrix3} left The first matrix.
- * @param {Matrix3} right The second matrix.
- * @param {Matrix3} result The object onto which to store the result.
- * @returns {Matrix3} The modified result parameter.
- */
- Matrix3.add = function (left, right, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("left", left);
- Check.Check.typeOf.object("right", right);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- result[0] = left[0] + right[0];
- result[1] = left[1] + right[1];
- result[2] = left[2] + right[2];
- result[3] = left[3] + right[3];
- result[4] = left[4] + right[4];
- result[5] = left[5] + right[5];
- result[6] = left[6] + right[6];
- result[7] = left[7] + right[7];
- result[8] = left[8] + right[8];
- return result;
- };
- /**
- * Computes the difference of two matrices.
- *
- * @param {Matrix3} left The first matrix.
- * @param {Matrix3} right The second matrix.
- * @param {Matrix3} result The object onto which to store the result.
- * @returns {Matrix3} The modified result parameter.
- */
- Matrix3.subtract = function (left, right, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("left", left);
- Check.Check.typeOf.object("right", right);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- result[0] = left[0] - right[0];
- result[1] = left[1] - right[1];
- result[2] = left[2] - right[2];
- result[3] = left[3] - right[3];
- result[4] = left[4] - right[4];
- result[5] = left[5] - right[5];
- result[6] = left[6] - right[6];
- result[7] = left[7] - right[7];
- result[8] = left[8] - right[8];
- return result;
- };
- /**
- * Computes the product of a matrix and a column vector.
- *
- * @param {Matrix3} matrix The matrix.
- * @param {Cartesian3} cartesian The column.
- * @param {Cartesian3} result The object onto which to store the result.
- * @returns {Cartesian3} The modified result parameter.
- */
- Matrix3.multiplyByVector = function (matrix, cartesian, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- Check.Check.typeOf.object("cartesian", cartesian);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- var vX = cartesian.x;
- var vY = cartesian.y;
- var vZ = cartesian.z;
- var x = matrix[0] * vX + matrix[3] * vY + matrix[6] * vZ;
- var y = matrix[1] * vX + matrix[4] * vY + matrix[7] * vZ;
- var z = matrix[2] * vX + matrix[5] * vY + matrix[8] * vZ;
- result.x = x;
- result.y = y;
- result.z = z;
- return result;
- };
- /**
- * Computes the product of a matrix and a scalar.
- *
- * @param {Matrix3} matrix The matrix.
- * @param {Number} scalar The number to multiply by.
- * @param {Matrix3} result The object onto which to store the result.
- * @returns {Matrix3} The modified result parameter.
- */
- Matrix3.multiplyByScalar = function (matrix, scalar, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- Check.Check.typeOf.number("scalar", scalar);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- result[0] = matrix[0] * scalar;
- result[1] = matrix[1] * scalar;
- result[2] = matrix[2] * scalar;
- result[3] = matrix[3] * scalar;
- result[4] = matrix[4] * scalar;
- result[5] = matrix[5] * scalar;
- result[6] = matrix[6] * scalar;
- result[7] = matrix[7] * scalar;
- result[8] = matrix[8] * scalar;
- return result;
- };
- /**
- * Computes the product of a matrix times a (non-uniform) scale, as if the scale were a scale matrix.
- *
- * @param {Matrix3} matrix The matrix on the left-hand side.
- * @param {Cartesian3} scale The non-uniform scale on the right-hand side.
- * @param {Matrix3} result The object onto which to store the result.
- * @returns {Matrix3} The modified result parameter.
- *
- *
- * @example
- * // Instead of Cesium.Matrix3.multiply(m, Cesium.Matrix3.fromScale(scale), m);
- * Cesium.Matrix3.multiplyByScale(m, scale, m);
- *
- * @see Matrix3.fromScale
- * @see Matrix3.multiplyByUniformScale
- */
- Matrix3.multiplyByScale = function (matrix, scale, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- Check.Check.typeOf.object("scale", scale);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- result[0] = matrix[0] * scale.x;
- result[1] = matrix[1] * scale.x;
- result[2] = matrix[2] * scale.x;
- result[3] = matrix[3] * scale.y;
- result[4] = matrix[4] * scale.y;
- result[5] = matrix[5] * scale.y;
- result[6] = matrix[6] * scale.z;
- result[7] = matrix[7] * scale.z;
- result[8] = matrix[8] * scale.z;
- return result;
- };
- /**
- * Creates a negated copy of the provided matrix.
- *
- * @param {Matrix3} matrix The matrix to negate.
- * @param {Matrix3} result The object onto which to store the result.
- * @returns {Matrix3} The modified result parameter.
- */
- Matrix3.negate = function (matrix, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- result[0] = -matrix[0];
- result[1] = -matrix[1];
- result[2] = -matrix[2];
- result[3] = -matrix[3];
- result[4] = -matrix[4];
- result[5] = -matrix[5];
- result[6] = -matrix[6];
- result[7] = -matrix[7];
- result[8] = -matrix[8];
- return result;
- };
- /**
- * Computes the transpose of the provided matrix.
- *
- * @param {Matrix3} matrix The matrix to transpose.
- * @param {Matrix3} result The object onto which to store the result.
- * @returns {Matrix3} The modified result parameter.
- */
- Matrix3.transpose = function (matrix, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- var column0Row0 = matrix[0];
- var column0Row1 = matrix[3];
- var column0Row2 = matrix[6];
- var column1Row0 = matrix[1];
- var column1Row1 = matrix[4];
- var column1Row2 = matrix[7];
- var column2Row0 = matrix[2];
- var column2Row1 = matrix[5];
- var column2Row2 = matrix[8];
- result[0] = column0Row0;
- result[1] = column0Row1;
- result[2] = column0Row2;
- result[3] = column1Row0;
- result[4] = column1Row1;
- result[5] = column1Row2;
- result[6] = column2Row0;
- result[7] = column2Row1;
- result[8] = column2Row2;
- return result;
- };
- var UNIT = new Cartesian2.Cartesian3(1, 1, 1);
- /**
- * Extracts the rotation assuming the matrix is an affine transformation.
- *
- * @param {Matrix3} matrix The matrix.
- * @param {Matrix3} result The object onto which to store the result.
- * @returns {Matrix3} The modified result parameter
- */
- Matrix3.getRotation = function (matrix, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- var inverseScale = Cartesian2.Cartesian3.divideComponents(
- UNIT,
- Matrix3.getScale(matrix, scratchScale),
- scratchScale
- );
- result = Matrix3.multiplyByScale(matrix, inverseScale, result);
- return result;
- };
- function computeFrobeniusNorm(matrix) {
- var norm = 0.0;
- for (var i = 0; i < 9; ++i) {
- var temp = matrix[i];
- norm += temp * temp;
- }
- return Math.sqrt(norm);
- }
- var rowVal = [1, 0, 0];
- var colVal = [2, 2, 1];
- function offDiagonalFrobeniusNorm(matrix) {
- // Computes the "off-diagonal" Frobenius norm.
- // Assumes matrix is symmetric.
- var norm = 0.0;
- for (var i = 0; i < 3; ++i) {
- var temp = matrix[Matrix3.getElementIndex(colVal[i], rowVal[i])];
- norm += 2.0 * temp * temp;
- }
- return Math.sqrt(norm);
- }
- function shurDecomposition(matrix, result) {
- // This routine was created based upon Matrix Computations, 3rd ed., by Golub and Van Loan,
- // section 8.4.2 The 2by2 Symmetric Schur Decomposition.
- //
- // The routine takes a matrix, which is assumed to be symmetric, and
- // finds the largest off-diagonal term, and then creates
- // a matrix (result) which can be used to help reduce it
- var tolerance = _Math.CesiumMath.EPSILON15;
- var maxDiagonal = 0.0;
- var rotAxis = 1;
- // find pivot (rotAxis) based on max diagonal of matrix
- for (var i = 0; i < 3; ++i) {
- var temp = Math.abs(matrix[Matrix3.getElementIndex(colVal[i], rowVal[i])]);
- if (temp > maxDiagonal) {
- rotAxis = i;
- maxDiagonal = temp;
- }
- }
- var c = 1.0;
- var s = 0.0;
- var p = rowVal[rotAxis];
- var q = colVal[rotAxis];
- if (Math.abs(matrix[Matrix3.getElementIndex(q, p)]) > tolerance) {
- var qq = matrix[Matrix3.getElementIndex(q, q)];
- var pp = matrix[Matrix3.getElementIndex(p, p)];
- var qp = matrix[Matrix3.getElementIndex(q, p)];
- var tau = (qq - pp) / 2.0 / qp;
- var t;
- if (tau < 0.0) {
- t = -1.0 / (-tau + Math.sqrt(1.0 + tau * tau));
- } else {
- t = 1.0 / (tau + Math.sqrt(1.0 + tau * tau));
- }
- c = 1.0 / Math.sqrt(1.0 + t * t);
- s = t * c;
- }
- result = Matrix3.clone(Matrix3.IDENTITY, result);
- result[Matrix3.getElementIndex(p, p)] = result[
- Matrix3.getElementIndex(q, q)
- ] = c;
- result[Matrix3.getElementIndex(q, p)] = s;
- result[Matrix3.getElementIndex(p, q)] = -s;
- return result;
- }
- var jMatrix = new Matrix3();
- var jMatrixTranspose = new Matrix3();
- /**
- * Computes the eigenvectors and eigenvalues of a symmetric matrix.
- * <p>
- * Returns a diagonal matrix and unitary matrix such that:
- * <code>matrix = unitary matrix * diagonal matrix * transpose(unitary matrix)</code>
- * </p>
- * <p>
- * The values along the diagonal of the diagonal matrix are the eigenvalues. The columns
- * of the unitary matrix are the corresponding eigenvectors.
- * </p>
- *
- * @param {Matrix3} matrix The matrix to decompose into diagonal and unitary matrix. Expected to be symmetric.
- * @param {Object} [result] An object with unitary and diagonal properties which are matrices onto which to store the result.
- * @returns {Object} An object with unitary and diagonal properties which are the unitary and diagonal matrices, respectively.
- *
- * @example
- * var a = //... symetric matrix
- * var result = {
- * unitary : new Cesium.Matrix3(),
- * diagonal : new Cesium.Matrix3()
- * };
- * Cesium.Matrix3.computeEigenDecomposition(a, result);
- *
- * var unitaryTranspose = Cesium.Matrix3.transpose(result.unitary, new Cesium.Matrix3());
- * var b = Cesium.Matrix3.multiply(result.unitary, result.diagonal, new Cesium.Matrix3());
- * Cesium.Matrix3.multiply(b, unitaryTranspose, b); // b is now equal to a
- *
- * var lambda = Cesium.Matrix3.getColumn(result.diagonal, 0, new Cesium.Cartesian3()).x; // first eigenvalue
- * var v = Cesium.Matrix3.getColumn(result.unitary, 0, new Cesium.Cartesian3()); // first eigenvector
- * var c = Cesium.Cartesian3.multiplyByScalar(v, lambda, new Cesium.Cartesian3()); // equal to Cesium.Matrix3.multiplyByVector(a, v)
- */
- Matrix3.computeEigenDecomposition = function (matrix, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- //>>includeEnd('debug');
- // This routine was created based upon Matrix Computations, 3rd ed., by Golub and Van Loan,
- // section 8.4.3 The Classical Jacobi Algorithm
- var tolerance = _Math.CesiumMath.EPSILON20;
- var maxSweeps = 10;
- var count = 0;
- var sweep = 0;
- if (!when.defined(result)) {
- result = {};
- }
- var unitaryMatrix = (result.unitary = Matrix3.clone(
- Matrix3.IDENTITY,
- result.unitary
- ));
- var diagMatrix = (result.diagonal = Matrix3.clone(matrix, result.diagonal));
- var epsilon = tolerance * computeFrobeniusNorm(diagMatrix);
- while (sweep < maxSweeps && offDiagonalFrobeniusNorm(diagMatrix) > epsilon) {
- shurDecomposition(diagMatrix, jMatrix);
- Matrix3.transpose(jMatrix, jMatrixTranspose);
- Matrix3.multiply(diagMatrix, jMatrix, diagMatrix);
- Matrix3.multiply(jMatrixTranspose, diagMatrix, diagMatrix);
- Matrix3.multiply(unitaryMatrix, jMatrix, unitaryMatrix);
- if (++count > 2) {
- ++sweep;
- count = 0;
- }
- }
- return result;
- };
- /**
- * Computes a matrix, which contains the absolute (unsigned) values of the provided matrix's elements.
- *
- * @param {Matrix3} matrix The matrix with signed elements.
- * @param {Matrix3} result The object onto which to store the result.
- * @returns {Matrix3} The modified result parameter.
- */
- Matrix3.abs = function (matrix, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- result[0] = Math.abs(matrix[0]);
- result[1] = Math.abs(matrix[1]);
- result[2] = Math.abs(matrix[2]);
- result[3] = Math.abs(matrix[3]);
- result[4] = Math.abs(matrix[4]);
- result[5] = Math.abs(matrix[5]);
- result[6] = Math.abs(matrix[6]);
- result[7] = Math.abs(matrix[7]);
- result[8] = Math.abs(matrix[8]);
- return result;
- };
- /**
- * Computes the determinant of the provided matrix.
- *
- * @param {Matrix3} matrix The matrix to use.
- * @returns {Number} The value of the determinant of the matrix.
- */
- Matrix3.determinant = function (matrix) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- //>>includeEnd('debug');
- var m11 = matrix[0];
- var m21 = matrix[3];
- var m31 = matrix[6];
- var m12 = matrix[1];
- var m22 = matrix[4];
- var m32 = matrix[7];
- var m13 = matrix[2];
- var m23 = matrix[5];
- var m33 = matrix[8];
- return (
- m11 * (m22 * m33 - m23 * m32) +
- m12 * (m23 * m31 - m21 * m33) +
- m13 * (m21 * m32 - m22 * m31)
- );
- };
- /**
- * Computes the inverse of the provided matrix.
- *
- * @param {Matrix3} matrix The matrix to invert.
- * @param {Matrix3} result The object onto which to store the result.
- * @returns {Matrix3} The modified result parameter.
- *
- * @exception {DeveloperError} matrix is not invertible.
- */
- Matrix3.inverse = function (matrix, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- var m11 = matrix[0];
- var m21 = matrix[1];
- var m31 = matrix[2];
- var m12 = matrix[3];
- var m22 = matrix[4];
- var m32 = matrix[5];
- var m13 = matrix[6];
- var m23 = matrix[7];
- var m33 = matrix[8];
- var determinant = Matrix3.determinant(matrix);
- //>>includeStart('debug', pragmas.debug);
- if (Math.abs(determinant) <= _Math.CesiumMath.EPSILON15) {
- throw new Check.DeveloperError("matrix is not invertible");
- }
- //>>includeEnd('debug');
- result[0] = m22 * m33 - m23 * m32;
- result[1] = m23 * m31 - m21 * m33;
- result[2] = m21 * m32 - m22 * m31;
- result[3] = m13 * m32 - m12 * m33;
- result[4] = m11 * m33 - m13 * m31;
- result[5] = m12 * m31 - m11 * m32;
- result[6] = m12 * m23 - m13 * m22;
- result[7] = m13 * m21 - m11 * m23;
- result[8] = m11 * m22 - m12 * m21;
- var scale = 1.0 / determinant;
- return Matrix3.multiplyByScalar(result, scale, result);
- };
- /**
- * Compares the provided matrices componentwise and returns
- * <code>true</code> if they are equal, <code>false</code> otherwise.
- *
- * @param {Matrix3} [left] The first matrix.
- * @param {Matrix3} [right] The second matrix.
- * @returns {Boolean} <code>true</code> if left and right are equal, <code>false</code> otherwise.
- */
- Matrix3.equals = function (left, right) {
- return (
- left === right ||
- (when.defined(left) &&
- when.defined(right) &&
- left[0] === right[0] &&
- left[1] === right[1] &&
- left[2] === right[2] &&
- left[3] === right[3] &&
- left[4] === right[4] &&
- left[5] === right[5] &&
- left[6] === right[6] &&
- left[7] === right[7] &&
- left[8] === right[8])
- );
- };
- /**
- * Compares the provided matrices componentwise and returns
- * <code>true</code> if they are within the provided epsilon,
- * <code>false</code> otherwise.
- *
- * @param {Matrix3} [left] The first matrix.
- * @param {Matrix3} [right] The second matrix.
- * @param {Number} [epsilon=0] The epsilon to use for equality testing.
- * @returns {Boolean} <code>true</code> if left and right are within the provided epsilon, <code>false</code> otherwise.
- */
- Matrix3.equalsEpsilon = function (left, right, epsilon) {
- epsilon = when.defaultValue(epsilon, 0);
- return (
- left === right ||
- (when.defined(left) &&
- when.defined(right) &&
- Math.abs(left[0] - right[0]) <= epsilon &&
- Math.abs(left[1] - right[1]) <= epsilon &&
- Math.abs(left[2] - right[2]) <= epsilon &&
- Math.abs(left[3] - right[3]) <= epsilon &&
- Math.abs(left[4] - right[4]) <= epsilon &&
- Math.abs(left[5] - right[5]) <= epsilon &&
- Math.abs(left[6] - right[6]) <= epsilon &&
- Math.abs(left[7] - right[7]) <= epsilon &&
- Math.abs(left[8] - right[8]) <= epsilon)
- );
- };
- /**
- * An immutable Matrix3 instance initialized to the identity matrix.
- *
- * @type {Matrix3}
- * @constant
- */
- Matrix3.IDENTITY = Object.freeze(
- new Matrix3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0)
- );
- /**
- * An immutable Matrix3 instance initialized to the zero matrix.
- *
- * @type {Matrix3}
- * @constant
- */
- Matrix3.ZERO = Object.freeze(
- new Matrix3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
- );
- /**
- * The index into Matrix3 for column 0, row 0.
- *
- * @type {Number}
- * @constant
- */
- Matrix3.COLUMN0ROW0 = 0;
- /**
- * The index into Matrix3 for column 0, row 1.
- *
- * @type {Number}
- * @constant
- */
- Matrix3.COLUMN0ROW1 = 1;
- /**
- * The index into Matrix3 for column 0, row 2.
- *
- * @type {Number}
- * @constant
- */
- Matrix3.COLUMN0ROW2 = 2;
- /**
- * The index into Matrix3 for column 1, row 0.
- *
- * @type {Number}
- * @constant
- */
- Matrix3.COLUMN1ROW0 = 3;
- /**
- * The index into Matrix3 for column 1, row 1.
- *
- * @type {Number}
- * @constant
- */
- Matrix3.COLUMN1ROW1 = 4;
- /**
- * The index into Matrix3 for column 1, row 2.
- *
- * @type {Number}
- * @constant
- */
- Matrix3.COLUMN1ROW2 = 5;
- /**
- * The index into Matrix3 for column 2, row 0.
- *
- * @type {Number}
- * @constant
- */
- Matrix3.COLUMN2ROW0 = 6;
- /**
- * The index into Matrix3 for column 2, row 1.
- *
- * @type {Number}
- * @constant
- */
- Matrix3.COLUMN2ROW1 = 7;
- /**
- * The index into Matrix3 for column 2, row 2.
- *
- * @type {Number}
- * @constant
- */
- Matrix3.COLUMN2ROW2 = 8;
- Object.defineProperties(Matrix3.prototype, {
- /**
- * Gets the number of items in the collection.
- * @memberof Matrix3.prototype
- *
- * @type {Number}
- */
- length: {
- get: function () {
- return Matrix3.packedLength;
- },
- },
- });
- /**
- * Duplicates the provided Matrix3 instance.
- *
- * @param {Matrix3} [result] The object onto which to store the result.
- * @returns {Matrix3} The modified result parameter or a new Matrix3 instance if one was not provided.
- */
- Matrix3.prototype.clone = function (result) {
- return Matrix3.clone(this, result);
- };
- /**
- * Compares this matrix to the provided matrix componentwise and returns
- * <code>true</code> if they are equal, <code>false</code> otherwise.
- *
- * @param {Matrix3} [right] The right hand side matrix.
- * @returns {Boolean} <code>true</code> if they are equal, <code>false</code> otherwise.
- */
- Matrix3.prototype.equals = function (right) {
- return Matrix3.equals(this, right);
- };
- /**
- * @private
- */
- Matrix3.equalsArray = function (matrix, array, offset) {
- return (
- matrix[0] === array[offset] &&
- matrix[1] === array[offset + 1] &&
- matrix[2] === array[offset + 2] &&
- matrix[3] === array[offset + 3] &&
- matrix[4] === array[offset + 4] &&
- matrix[5] === array[offset + 5] &&
- matrix[6] === array[offset + 6] &&
- matrix[7] === array[offset + 7] &&
- matrix[8] === array[offset + 8]
- );
- };
- /**
- * Compares this matrix to the provided matrix componentwise and returns
- * <code>true</code> if they are within the provided epsilon,
- * <code>false</code> otherwise.
- *
- * @param {Matrix3} [right] The right hand side matrix.
- * @param {Number} [epsilon=0] The epsilon to use for equality testing.
- * @returns {Boolean} <code>true</code> if they are within the provided epsilon, <code>false</code> otherwise.
- */
- Matrix3.prototype.equalsEpsilon = function (right, epsilon) {
- return Matrix3.equalsEpsilon(this, right, epsilon);
- };
- /**
- * Creates a string representing this Matrix with each row being
- * on a separate line and in the format '(column0, column1, column2)'.
- *
- * @returns {String} A string representing the provided Matrix with each row being on a separate line and in the format '(column0, column1, column2)'.
- */
- Matrix3.prototype.toString = function () {
- return (
- "(" +
- this[0] +
- ", " +
- this[3] +
- ", " +
- this[6] +
- ")\n" +
- "(" +
- this[1] +
- ", " +
- this[4] +
- ", " +
- this[7] +
- ")\n" +
- "(" +
- this[2] +
- ", " +
- this[5] +
- ", " +
- this[8] +
- ")"
- );
- };
- /**
- * A 4D Cartesian point.
- * @alias Cartesian4
- * @constructor
- *
- * @param {Number} [x=0.0] The X component.
- * @param {Number} [y=0.0] The Y component.
- * @param {Number} [z=0.0] The Z component.
- * @param {Number} [w=0.0] The W component.
- *
- * @see Cartesian2
- * @see Cartesian3
- * @see Packable
- */
- function Cartesian4(x, y, z, w) {
- /**
- * The X component.
- * @type {Number}
- * @default 0.0
- */
- this.x = when.defaultValue(x, 0.0);
- /**
- * The Y component.
- * @type {Number}
- * @default 0.0
- */
- this.y = when.defaultValue(y, 0.0);
- /**
- * The Z component.
- * @type {Number}
- * @default 0.0
- */
- this.z = when.defaultValue(z, 0.0);
- /**
- * The W component.
- * @type {Number}
- * @default 0.0
- */
- this.w = when.defaultValue(w, 0.0);
- }
- /**
- * Creates a Cartesian4 instance from x, y, z and w coordinates.
- *
- * @param {Number} x The x coordinate.
- * @param {Number} y The y coordinate.
- * @param {Number} z The z coordinate.
- * @param {Number} w The w coordinate.
- * @param {Cartesian4} [result] The object onto which to store the result.
- * @returns {Cartesian4} The modified result parameter or a new Cartesian4 instance if one was not provided.
- */
- Cartesian4.fromElements = function (x, y, z, w, result) {
- if (!when.defined(result)) {
- return new Cartesian4(x, y, z, w);
- }
- result.x = x;
- result.y = y;
- result.z = z;
- result.w = w;
- return result;
- };
- /**
- * Creates a Cartesian4 instance from a {@link Color}. <code>red</code>, <code>green</code>, <code>blue</code>,
- * and <code>alpha</code> map to <code>x</code>, <code>y</code>, <code>z</code>, and <code>w</code>, respectively.
- *
- * @param {Color} color The source color.
- * @param {Cartesian4} [result] The object onto which to store the result.
- * @returns {Cartesian4} The modified result parameter or a new Cartesian4 instance if one was not provided.
- */
- Cartesian4.fromColor = function (color, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("color", color);
- //>>includeEnd('debug');
- if (!when.defined(result)) {
- return new Cartesian4(color.red, color.green, color.blue, color.alpha);
- }
- result.x = color.red;
- result.y = color.green;
- result.z = color.blue;
- result.w = color.alpha;
- return result;
- };
- /**
- * Duplicates a Cartesian4 instance.
- *
- * @param {Cartesian4} cartesian The Cartesian to duplicate.
- * @param {Cartesian4} [result] The object onto which to store the result.
- * @returns {Cartesian4} The modified result parameter or a new Cartesian4 instance if one was not provided. (Returns undefined if cartesian is undefined)
- */
- Cartesian4.clone = function (cartesian, result) {
- if (!when.defined(cartesian)) {
- return undefined;
- }
- if (!when.defined(result)) {
- return new Cartesian4(cartesian.x, cartesian.y, cartesian.z, cartesian.w);
- }
- result.x = cartesian.x;
- result.y = cartesian.y;
- result.z = cartesian.z;
- result.w = cartesian.w;
- return result;
- };
- /**
- * The number of elements used to pack the object into an array.
- * @type {Number}
- */
- Cartesian4.packedLength = 4;
- /**
- * Stores the provided instance into the provided array.
- *
- * @param {Cartesian4} value The value to pack.
- * @param {Number[]} array The array to pack into.
- * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.
- *
- * @returns {Number[]} The array that was packed into
- */
- Cartesian4.pack = function (value, array, startingIndex) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("value", value);
- Check.Check.defined("array", array);
- //>>includeEnd('debug');
- startingIndex = when.defaultValue(startingIndex, 0);
- array[startingIndex++] = value.x;
- array[startingIndex++] = value.y;
- array[startingIndex++] = value.z;
- array[startingIndex] = value.w;
- return array;
- };
- /**
- * Retrieves an instance from a packed array.
- *
- * @param {Number[]} array The packed array.
- * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.
- * @param {Cartesian4} [result] The object into which to store the result.
- * @returns {Cartesian4} The modified result parameter or a new Cartesian4 instance if one was not provided.
- */
- Cartesian4.unpack = function (array, startingIndex, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.defined("array", array);
- //>>includeEnd('debug');
- startingIndex = when.defaultValue(startingIndex, 0);
- if (!when.defined(result)) {
- result = new Cartesian4();
- }
- result.x = array[startingIndex++];
- result.y = array[startingIndex++];
- result.z = array[startingIndex++];
- result.w = array[startingIndex];
- return result;
- };
- /**
- * Flattens an array of Cartesian4s into and array of components.
- *
- * @param {Cartesian4[]} array The array of cartesians to pack.
- * @param {Number[]} [result] The array onto which to store the result. If this is a typed array, it must have array.length * 4 components, else a {@link DeveloperError} will be thrown. If it is a regular array, it will be resized to have (array.length * 4) elements.
- * @returns {Number[]} The packed array.
- */
- Cartesian4.packArray = function (array, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.defined("array", array);
- //>>includeEnd('debug');
- var length = array.length;
- var resultLength = length * 4;
- if (!when.defined(result)) {
- result = new Array(resultLength);
- } else if (!Array.isArray(result) && result.length !== resultLength) {
- throw new Check.DeveloperError(
- "If result is a typed array, it must have exactly array.length * 4 elements"
- );
- } else if (result.length !== resultLength) {
- result.length = resultLength;
- }
- for (var i = 0; i < length; ++i) {
- Cartesian4.pack(array[i], result, i * 4);
- }
- return result;
- };
- /**
- * Unpacks an array of cartesian components into and array of Cartesian4s.
- *
- * @param {Number[]} array The array of components to unpack.
- * @param {Cartesian4[]} [result] The array onto which to store the result.
- * @returns {Cartesian4[]} The unpacked array.
- */
- Cartesian4.unpackArray = function (array, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.defined("array", array);
- Check.Check.typeOf.number.greaterThanOrEquals("array.length", array.length, 4);
- if (array.length % 4 !== 0) {
- throw new Check.DeveloperError("array length must be a multiple of 4.");
- }
- //>>includeEnd('debug');
- var length = array.length;
- if (!when.defined(result)) {
- result = new Array(length / 4);
- } else {
- result.length = length / 4;
- }
- for (var i = 0; i < length; i += 4) {
- var index = i / 4;
- result[index] = Cartesian4.unpack(array, i, result[index]);
- }
- return result;
- };
- /**
- * Creates a Cartesian4 from four consecutive elements in an array.
- * @function
- *
- * @param {Number[]} array The array whose four consecutive elements correspond to the x, y, z, and w components, respectively.
- * @param {Number} [startingIndex=0] The offset into the array of the first element, which corresponds to the x component.
- * @param {Cartesian4} [result] The object onto which to store the result.
- * @returns {Cartesian4} The modified result parameter or a new Cartesian4 instance if one was not provided.
- *
- * @example
- * // Create a Cartesian4 with (1.0, 2.0, 3.0, 4.0)
- * var v = [1.0, 2.0, 3.0, 4.0];
- * var p = Cesium.Cartesian4.fromArray(v);
- *
- * // Create a Cartesian4 with (1.0, 2.0, 3.0, 4.0) using an offset into an array
- * var v2 = [0.0, 0.0, 1.0, 2.0, 3.0, 4.0];
- * var p2 = Cesium.Cartesian4.fromArray(v2, 2);
- */
- Cartesian4.fromArray = Cartesian4.unpack;
- /**
- * Computes the value of the maximum component for the supplied Cartesian.
- *
- * @param {Cartesian4} cartesian The cartesian to use.
- * @returns {Number} The value of the maximum component.
- */
- Cartesian4.maximumComponent = function (cartesian) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("cartesian", cartesian);
- //>>includeEnd('debug');
- return Math.max(cartesian.x, cartesian.y, cartesian.z, cartesian.w);
- };
- /**
- * Computes the value of the minimum component for the supplied Cartesian.
- *
- * @param {Cartesian4} cartesian The cartesian to use.
- * @returns {Number} The value of the minimum component.
- */
- Cartesian4.minimumComponent = function (cartesian) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("cartesian", cartesian);
- //>>includeEnd('debug');
- return Math.min(cartesian.x, cartesian.y, cartesian.z, cartesian.w);
- };
- /**
- * Compares two Cartesians and computes a Cartesian which contains the minimum components of the supplied Cartesians.
- *
- * @param {Cartesian4} first A cartesian to compare.
- * @param {Cartesian4} second A cartesian to compare.
- * @param {Cartesian4} result The object into which to store the result.
- * @returns {Cartesian4} A cartesian with the minimum components.
- */
- Cartesian4.minimumByComponent = function (first, second, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("first", first);
- Check.Check.typeOf.object("second", second);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- result.x = Math.min(first.x, second.x);
- result.y = Math.min(first.y, second.y);
- result.z = Math.min(first.z, second.z);
- result.w = Math.min(first.w, second.w);
- return result;
- };
- /**
- * Compares two Cartesians and computes a Cartesian which contains the maximum components of the supplied Cartesians.
- *
- * @param {Cartesian4} first A cartesian to compare.
- * @param {Cartesian4} second A cartesian to compare.
- * @param {Cartesian4} result The object into which to store the result.
- * @returns {Cartesian4} A cartesian with the maximum components.
- */
- Cartesian4.maximumByComponent = function (first, second, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("first", first);
- Check.Check.typeOf.object("second", second);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- result.x = Math.max(first.x, second.x);
- result.y = Math.max(first.y, second.y);
- result.z = Math.max(first.z, second.z);
- result.w = Math.max(first.w, second.w);
- return result;
- };
- /**
- * Computes the provided Cartesian's squared magnitude.
- *
- * @param {Cartesian4} cartesian The Cartesian instance whose squared magnitude is to be computed.
- * @returns {Number} The squared magnitude.
- */
- Cartesian4.magnitudeSquared = function (cartesian) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("cartesian", cartesian);
- //>>includeEnd('debug');
- return (
- cartesian.x * cartesian.x +
- cartesian.y * cartesian.y +
- cartesian.z * cartesian.z +
- cartesian.w * cartesian.w
- );
- };
- /**
- * Computes the Cartesian's magnitude (length).
- *
- * @param {Cartesian4} cartesian The Cartesian instance whose magnitude is to be computed.
- * @returns {Number} The magnitude.
- */
- Cartesian4.magnitude = function (cartesian) {
- return Math.sqrt(Cartesian4.magnitudeSquared(cartesian));
- };
- var distanceScratch = new Cartesian4();
- /**
- * Computes the 4-space distance between two points.
- *
- * @param {Cartesian4} left The first point to compute the distance from.
- * @param {Cartesian4} right The second point to compute the distance to.
- * @returns {Number} The distance between two points.
- *
- * @example
- * // Returns 1.0
- * var d = Cesium.Cartesian4.distance(
- * new Cesium.Cartesian4(1.0, 0.0, 0.0, 0.0),
- * new Cesium.Cartesian4(2.0, 0.0, 0.0, 0.0));
- */
- Cartesian4.distance = function (left, right) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("left", left);
- Check.Check.typeOf.object("right", right);
- //>>includeEnd('debug');
- Cartesian4.subtract(left, right, distanceScratch);
- return Cartesian4.magnitude(distanceScratch);
- };
- /**
- * Computes the squared distance between two points. Comparing squared distances
- * using this function is more efficient than comparing distances using {@link Cartesian4#distance}.
- *
- * @param {Cartesian4} left The first point to compute the distance from.
- * @param {Cartesian4} right The second point to compute the distance to.
- * @returns {Number} The distance between two points.
- *
- * @example
- * // Returns 4.0, not 2.0
- * var d = Cesium.Cartesian4.distance(
- * new Cesium.Cartesian4(1.0, 0.0, 0.0, 0.0),
- * new Cesium.Cartesian4(3.0, 0.0, 0.0, 0.0));
- */
- Cartesian4.distanceSquared = function (left, right) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("left", left);
- Check.Check.typeOf.object("right", right);
- //>>includeEnd('debug');
- Cartesian4.subtract(left, right, distanceScratch);
- return Cartesian4.magnitudeSquared(distanceScratch);
- };
- /**
- * Computes the normalized form of the supplied Cartesian.
- *
- * @param {Cartesian4} cartesian The Cartesian to be normalized.
- * @param {Cartesian4} result The object onto which to store the result.
- * @returns {Cartesian4} The modified result parameter.
- */
- Cartesian4.normalize = function (cartesian, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("cartesian", cartesian);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- var magnitude = Cartesian4.magnitude(cartesian);
- result.x = cartesian.x / magnitude;
- result.y = cartesian.y / magnitude;
- result.z = cartesian.z / magnitude;
- result.w = cartesian.w / magnitude;
- //>>includeStart('debug', pragmas.debug);
- if (
- isNaN(result.x) ||
- isNaN(result.y) ||
- isNaN(result.z) ||
- isNaN(result.w)
- ) {
- throw new Check.DeveloperError("normalized result is not a number");
- }
- //>>includeEnd('debug');
- return result;
- };
- /**
- * Computes the dot (scalar) product of two Cartesians.
- *
- * @param {Cartesian4} left The first Cartesian.
- * @param {Cartesian4} right The second Cartesian.
- * @returns {Number} The dot product.
- */
- Cartesian4.dot = function (left, right) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("left", left);
- Check.Check.typeOf.object("right", right);
- //>>includeEnd('debug');
- return (
- left.x * right.x + left.y * right.y + left.z * right.z + left.w * right.w
- );
- };
- /**
- * Computes the componentwise product of two Cartesians.
- *
- * @param {Cartesian4} left The first Cartesian.
- * @param {Cartesian4} right The second Cartesian.
- * @param {Cartesian4} result The object onto which to store the result.
- * @returns {Cartesian4} The modified result parameter.
- */
- Cartesian4.multiplyComponents = function (left, right, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("left", left);
- Check.Check.typeOf.object("right", right);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- result.x = left.x * right.x;
- result.y = left.y * right.y;
- result.z = left.z * right.z;
- result.w = left.w * right.w;
- return result;
- };
- /**
- * Computes the componentwise quotient of two Cartesians.
- *
- * @param {Cartesian4} left The first Cartesian.
- * @param {Cartesian4} right The second Cartesian.
- * @param {Cartesian4} result The object onto which to store the result.
- * @returns {Cartesian4} The modified result parameter.
- */
- Cartesian4.divideComponents = function (left, right, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("left", left);
- Check.Check.typeOf.object("right", right);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- result.x = left.x / right.x;
- result.y = left.y / right.y;
- result.z = left.z / right.z;
- result.w = left.w / right.w;
- return result;
- };
- /**
- * Computes the componentwise sum of two Cartesians.
- *
- * @param {Cartesian4} left The first Cartesian.
- * @param {Cartesian4} right The second Cartesian.
- * @param {Cartesian4} result The object onto which to store the result.
- * @returns {Cartesian4} The modified result parameter.
- */
- Cartesian4.add = function (left, right, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("left", left);
- Check.Check.typeOf.object("right", right);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- result.x = left.x + right.x;
- result.y = left.y + right.y;
- result.z = left.z + right.z;
- result.w = left.w + right.w;
- return result;
- };
- /**
- * Computes the componentwise difference of two Cartesians.
- *
- * @param {Cartesian4} left The first Cartesian.
- * @param {Cartesian4} right The second Cartesian.
- * @param {Cartesian4} result The object onto which to store the result.
- * @returns {Cartesian4} The modified result parameter.
- */
- Cartesian4.subtract = function (left, right, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("left", left);
- Check.Check.typeOf.object("right", right);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- result.x = left.x - right.x;
- result.y = left.y - right.y;
- result.z = left.z - right.z;
- result.w = left.w - right.w;
- return result;
- };
- /**
- * Multiplies the provided Cartesian componentwise by the provided scalar.
- *
- * @param {Cartesian4} cartesian The Cartesian to be scaled.
- * @param {Number} scalar The scalar to multiply with.
- * @param {Cartesian4} result The object onto which to store the result.
- * @returns {Cartesian4} The modified result parameter.
- */
- Cartesian4.multiplyByScalar = function (cartesian, scalar, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("cartesian", cartesian);
- Check.Check.typeOf.number("scalar", scalar);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- result.x = cartesian.x * scalar;
- result.y = cartesian.y * scalar;
- result.z = cartesian.z * scalar;
- result.w = cartesian.w * scalar;
- return result;
- };
- /**
- * Divides the provided Cartesian componentwise by the provided scalar.
- *
- * @param {Cartesian4} cartesian The Cartesian to be divided.
- * @param {Number} scalar The scalar to divide by.
- * @param {Cartesian4} result The object onto which to store the result.
- * @returns {Cartesian4} The modified result parameter.
- */
- Cartesian4.divideByScalar = function (cartesian, scalar, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("cartesian", cartesian);
- Check.Check.typeOf.number("scalar", scalar);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- result.x = cartesian.x / scalar;
- result.y = cartesian.y / scalar;
- result.z = cartesian.z / scalar;
- result.w = cartesian.w / scalar;
- return result;
- };
- /**
- * Negates the provided Cartesian.
- *
- * @param {Cartesian4} cartesian The Cartesian to be negated.
- * @param {Cartesian4} result The object onto which to store the result.
- * @returns {Cartesian4} The modified result parameter.
- */
- Cartesian4.negate = function (cartesian, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("cartesian", cartesian);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- result.x = -cartesian.x;
- result.y = -cartesian.y;
- result.z = -cartesian.z;
- result.w = -cartesian.w;
- return result;
- };
- /**
- * Computes the absolute value of the provided Cartesian.
- *
- * @param {Cartesian4} cartesian The Cartesian whose absolute value is to be computed.
- * @param {Cartesian4} result The object onto which to store the result.
- * @returns {Cartesian4} The modified result parameter.
- */
- Cartesian4.abs = function (cartesian, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("cartesian", cartesian);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- result.x = Math.abs(cartesian.x);
- result.y = Math.abs(cartesian.y);
- result.z = Math.abs(cartesian.z);
- result.w = Math.abs(cartesian.w);
- return result;
- };
- var lerpScratch = new Cartesian4();
- /**
- * Computes the linear interpolation or extrapolation at t using the provided cartesians.
- *
- * @param {Cartesian4} start The value corresponding to t at 0.0.
- * @param {Cartesian4}end The value corresponding to t at 1.0.
- * @param {Number} t The point along t at which to interpolate.
- * @param {Cartesian4} result The object onto which to store the result.
- * @returns {Cartesian4} The modified result parameter.
- */
- Cartesian4.lerp = function (start, end, t, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("start", start);
- Check.Check.typeOf.object("end", end);
- Check.Check.typeOf.number("t", t);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- Cartesian4.multiplyByScalar(end, t, lerpScratch);
- result = Cartesian4.multiplyByScalar(start, 1.0 - t, result);
- return Cartesian4.add(lerpScratch, result, result);
- };
- var mostOrthogonalAxisScratch = new Cartesian4();
- /**
- * Returns the axis that is most orthogonal to the provided Cartesian.
- *
- * @param {Cartesian4} cartesian The Cartesian on which to find the most orthogonal axis.
- * @param {Cartesian4} result The object onto which to store the result.
- * @returns {Cartesian4} The most orthogonal axis.
- */
- Cartesian4.mostOrthogonalAxis = function (cartesian, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("cartesian", cartesian);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- var f = Cartesian4.normalize(cartesian, mostOrthogonalAxisScratch);
- Cartesian4.abs(f, f);
- if (f.x <= f.y) {
- if (f.x <= f.z) {
- if (f.x <= f.w) {
- result = Cartesian4.clone(Cartesian4.UNIT_X, result);
- } else {
- result = Cartesian4.clone(Cartesian4.UNIT_W, result);
- }
- } else if (f.z <= f.w) {
- result = Cartesian4.clone(Cartesian4.UNIT_Z, result);
- } else {
- result = Cartesian4.clone(Cartesian4.UNIT_W, result);
- }
- } else if (f.y <= f.z) {
- if (f.y <= f.w) {
- result = Cartesian4.clone(Cartesian4.UNIT_Y, result);
- } else {
- result = Cartesian4.clone(Cartesian4.UNIT_W, result);
- }
- } else if (f.z <= f.w) {
- result = Cartesian4.clone(Cartesian4.UNIT_Z, result);
- } else {
- result = Cartesian4.clone(Cartesian4.UNIT_W, result);
- }
- return result;
- };
- /**
- * Compares the provided Cartesians componentwise and returns
- * <code>true</code> if they are equal, <code>false</code> otherwise.
- *
- * @param {Cartesian4} [left] The first Cartesian.
- * @param {Cartesian4} [right] The second Cartesian.
- * @returns {Boolean} <code>true</code> if left and right are equal, <code>false</code> otherwise.
- */
- Cartesian4.equals = function (left, right) {
- return (
- left === right ||
- (when.defined(left) &&
- when.defined(right) &&
- left.x === right.x &&
- left.y === right.y &&
- left.z === right.z &&
- left.w === right.w)
- );
- };
- /**
- * @private
- */
- Cartesian4.equalsArray = function (cartesian, array, offset) {
- return (
- cartesian.x === array[offset] &&
- cartesian.y === array[offset + 1] &&
- cartesian.z === array[offset + 2] &&
- cartesian.w === array[offset + 3]
- );
- };
- /**
- * Compares the provided Cartesians componentwise and returns
- * <code>true</code> if they pass an absolute or relative tolerance test,
- * <code>false</code> otherwise.
- *
- * @param {Cartesian4} [left] The first Cartesian.
- * @param {Cartesian4} [right] The second Cartesian.
- * @param {Number} [relativeEpsilon=0] The relative epsilon tolerance to use for equality testing.
- * @param {Number} [absoluteEpsilon=relativeEpsilon] The absolute epsilon tolerance to use for equality testing.
- * @returns {Boolean} <code>true</code> if left and right are within the provided epsilon, <code>false</code> otherwise.
- */
- Cartesian4.equalsEpsilon = function (
- left,
- right,
- relativeEpsilon,
- absoluteEpsilon
- ) {
- return (
- left === right ||
- (when.defined(left) &&
- when.defined(right) &&
- _Math.CesiumMath.equalsEpsilon(
- left.x,
- right.x,
- relativeEpsilon,
- absoluteEpsilon
- ) &&
- _Math.CesiumMath.equalsEpsilon(
- left.y,
- right.y,
- relativeEpsilon,
- absoluteEpsilon
- ) &&
- _Math.CesiumMath.equalsEpsilon(
- left.z,
- right.z,
- relativeEpsilon,
- absoluteEpsilon
- ) &&
- _Math.CesiumMath.equalsEpsilon(
- left.w,
- right.w,
- relativeEpsilon,
- absoluteEpsilon
- ))
- );
- };
- /**
- * An immutable Cartesian4 instance initialized to (0.0, 0.0, 0.0, 0.0).
- *
- * @type {Cartesian4}
- * @constant
- */
- Cartesian4.ZERO = Object.freeze(new Cartesian4(0.0, 0.0, 0.0, 0.0));
- /**
- * An immutable Cartesian4 instance initialized to (1.0, 0.0, 0.0, 0.0).
- *
- * @type {Cartesian4}
- * @constant
- */
- Cartesian4.UNIT_X = Object.freeze(new Cartesian4(1.0, 0.0, 0.0, 0.0));
- /**
- * An immutable Cartesian4 instance initialized to (0.0, 1.0, 0.0, 0.0).
- *
- * @type {Cartesian4}
- * @constant
- */
- Cartesian4.UNIT_Y = Object.freeze(new Cartesian4(0.0, 1.0, 0.0, 0.0));
- /**
- * An immutable Cartesian4 instance initialized to (0.0, 0.0, 1.0, 0.0).
- *
- * @type {Cartesian4}
- * @constant
- */
- Cartesian4.UNIT_Z = Object.freeze(new Cartesian4(0.0, 0.0, 1.0, 0.0));
- /**
- * An immutable Cartesian4 instance initialized to (0.0, 0.0, 0.0, 1.0).
- *
- * @type {Cartesian4}
- * @constant
- */
- Cartesian4.UNIT_W = Object.freeze(new Cartesian4(0.0, 0.0, 0.0, 1.0));
- /**
- * Duplicates this Cartesian4 instance.
- *
- * @param {Cartesian4} [result] The object onto which to store the result.
- * @returns {Cartesian4} The modified result parameter or a new Cartesian4 instance if one was not provided.
- */
- Cartesian4.prototype.clone = function (result) {
- return Cartesian4.clone(this, result);
- };
- /**
- * Compares this Cartesian against the provided Cartesian componentwise and returns
- * <code>true</code> if they are equal, <code>false</code> otherwise.
- *
- * @param {Cartesian4} [right] The right hand side Cartesian.
- * @returns {Boolean} <code>true</code> if they are equal, <code>false</code> otherwise.
- */
- Cartesian4.prototype.equals = function (right) {
- return Cartesian4.equals(this, right);
- };
- /**
- * Compares this Cartesian against the provided Cartesian componentwise and returns
- * <code>true</code> if they pass an absolute or relative tolerance test,
- * <code>false</code> otherwise.
- *
- * @param {Cartesian4} [right] The right hand side Cartesian.
- * @param {Number} [relativeEpsilon=0] The relative epsilon tolerance to use for equality testing.
- * @param {Number} [absoluteEpsilon=relativeEpsilon] The absolute epsilon tolerance to use for equality testing.
- * @returns {Boolean} <code>true</code> if they are within the provided epsilon, <code>false</code> otherwise.
- */
- Cartesian4.prototype.equalsEpsilon = function (
- right,
- relativeEpsilon,
- absoluteEpsilon
- ) {
- return Cartesian4.equalsEpsilon(
- this,
- right,
- relativeEpsilon,
- absoluteEpsilon
- );
- };
- /**
- * Creates a string representing this Cartesian in the format '(x, y, z, w)'.
- *
- * @returns {String} A string representing the provided Cartesian in the format '(x, y, z, w)'.
- */
- Cartesian4.prototype.toString = function () {
- return "(" + this.x + ", " + this.y + ", " + this.z + ", " + this.w + ")";
- };
- var scratchFloatArray = new Float32Array(1);
- var SHIFT_LEFT_8 = 256.0;
- var SHIFT_LEFT_16 = 65536.0;
- var SHIFT_LEFT_24 = 16777216.0;
- var SHIFT_RIGHT_8 = 1.0 / SHIFT_LEFT_8;
- var SHIFT_RIGHT_16 = 1.0 / SHIFT_LEFT_16;
- var SHIFT_RIGHT_24 = 1.0 / SHIFT_LEFT_24;
- var BIAS = 38.0;
- /**
- * Packs an arbitrary floating point value to 4 values representable using uint8.
- *
- * @param {Number} value A floating point number
- * @param {Cartesian4} [result] The Cartesian4 that will contain the packed float.
- * @returns {Cartesian4} A Cartesian4 representing the float packed to values in x, y, z, and w.
- */
- Cartesian4.packFloat = function (value, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.number("value", value);
- //>>includeEnd('debug');
- if (!when.defined(result)) {
- result = new Cartesian4();
- }
- // Force the value to 32 bit precision
- scratchFloatArray[0] = value;
- value = scratchFloatArray[0];
- if (value === 0.0) {
- return Cartesian4.clone(Cartesian4.ZERO, result);
- }
- var sign = value < 0.0 ? 1.0 : 0.0;
- var exponent;
- if (!isFinite(value)) {
- value = 0.1;
- exponent = BIAS;
- } else {
- value = Math.abs(value);
- exponent = Math.floor(_Math.CesiumMath.logBase(value, 10)) + 1.0;
- value = value / Math.pow(10.0, exponent);
- }
- var temp = value * SHIFT_LEFT_8;
- result.x = Math.floor(temp);
- temp = (temp - result.x) * SHIFT_LEFT_8;
- result.y = Math.floor(temp);
- temp = (temp - result.y) * SHIFT_LEFT_8;
- result.z = Math.floor(temp);
- result.w = (exponent + BIAS) * 2.0 + sign;
- return result;
- };
- /**
- * Unpacks a float packed using Cartesian4.packFloat.
- *
- * @param {Cartesian4} packedFloat A Cartesian4 containing a float packed to 4 values representable using uint8.
- * @returns {Number} The unpacked float.
- * @private
- */
- Cartesian4.unpackFloat = function (packedFloat) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("packedFloat", packedFloat);
- //>>includeEnd('debug');
- var temp = packedFloat.w / 2.0;
- var exponent = Math.floor(temp);
- var sign = (temp - exponent) * 2.0;
- exponent = exponent - BIAS;
- sign = sign * 2.0 - 1.0;
- sign = -sign;
- if (exponent >= BIAS) {
- return sign < 0.0 ? Number.NEGATIVE_INFINITY : Number.POSITIVE_INFINITY;
- }
- var unpacked = sign * packedFloat.x * SHIFT_RIGHT_8;
- unpacked += sign * packedFloat.y * SHIFT_RIGHT_16;
- unpacked += sign * packedFloat.z * SHIFT_RIGHT_24;
- return unpacked * Math.pow(10.0, exponent);
- };
- /**
- * A 4x4 matrix, indexable as a column-major order array.
- * Constructor parameters are in row-major order for code readability.
- * @alias Matrix4
- * @constructor
- * @implements {ArrayLike<number>}
- *
- * @param {Number} [column0Row0=0.0] The value for column 0, row 0.
- * @param {Number} [column1Row0=0.0] The value for column 1, row 0.
- * @param {Number} [column2Row0=0.0] The value for column 2, row 0.
- * @param {Number} [column3Row0=0.0] The value for column 3, row 0.
- * @param {Number} [column0Row1=0.0] The value for column 0, row 1.
- * @param {Number} [column1Row1=0.0] The value for column 1, row 1.
- * @param {Number} [column2Row1=0.0] The value for column 2, row 1.
- * @param {Number} [column3Row1=0.0] The value for column 3, row 1.
- * @param {Number} [column0Row2=0.0] The value for column 0, row 2.
- * @param {Number} [column1Row2=0.0] The value for column 1, row 2.
- * @param {Number} [column2Row2=0.0] The value for column 2, row 2.
- * @param {Number} [column3Row2=0.0] The value for column 3, row 2.
- * @param {Number} [column0Row3=0.0] The value for column 0, row 3.
- * @param {Number} [column1Row3=0.0] The value for column 1, row 3.
- * @param {Number} [column2Row3=0.0] The value for column 2, row 3.
- * @param {Number} [column3Row3=0.0] The value for column 3, row 3.
- *
- * @see Matrix4.fromColumnMajorArray
- * @see Matrix4.fromRowMajorArray
- * @see Matrix4.fromRotationTranslation
- * @see Matrix4.fromTranslationRotationScale
- * @see Matrix4.fromTranslationQuaternionRotationScale
- * @see Matrix4.fromTranslation
- * @see Matrix4.fromScale
- * @see Matrix4.fromUniformScale
- * @see Matrix4.fromCamera
- * @see Matrix4.computePerspectiveFieldOfView
- * @see Matrix4.computeOrthographicOffCenter
- * @see Matrix4.computePerspectiveOffCenter
- * @see Matrix4.computeInfinitePerspectiveOffCenter
- * @see Matrix4.computeViewportTransformation
- * @see Matrix4.computeView
- * @see Matrix2
- * @see Matrix3
- * @see Packable
- */
- function Matrix4(
- column0Row0,
- column1Row0,
- column2Row0,
- column3Row0,
- column0Row1,
- column1Row1,
- column2Row1,
- column3Row1,
- column0Row2,
- column1Row2,
- column2Row2,
- column3Row2,
- column0Row3,
- column1Row3,
- column2Row3,
- column3Row3
- ) {
- this[0] = when.defaultValue(column0Row0, 0.0);
- this[1] = when.defaultValue(column0Row1, 0.0);
- this[2] = when.defaultValue(column0Row2, 0.0);
- this[3] = when.defaultValue(column0Row3, 0.0);
- this[4] = when.defaultValue(column1Row0, 0.0);
- this[5] = when.defaultValue(column1Row1, 0.0);
- this[6] = when.defaultValue(column1Row2, 0.0);
- this[7] = when.defaultValue(column1Row3, 0.0);
- this[8] = when.defaultValue(column2Row0, 0.0);
- this[9] = when.defaultValue(column2Row1, 0.0);
- this[10] = when.defaultValue(column2Row2, 0.0);
- this[11] = when.defaultValue(column2Row3, 0.0);
- this[12] = when.defaultValue(column3Row0, 0.0);
- this[13] = when.defaultValue(column3Row1, 0.0);
- this[14] = when.defaultValue(column3Row2, 0.0);
- this[15] = when.defaultValue(column3Row3, 0.0);
- }
- /**
- * The number of elements used to pack the object into an array.
- * @type {Number}
- */
- Matrix4.packedLength = 16;
- /**
- * Stores the provided instance into the provided array.
- *
- * @param {Matrix4} value The value to pack.
- * @param {Number[]} array The array to pack into.
- * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.
- *
- * @returns {Number[]} The array that was packed into
- */
- Matrix4.pack = function (value, array, startingIndex) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("value", value);
- Check.Check.defined("array", array);
- //>>includeEnd('debug');
- startingIndex = when.defaultValue(startingIndex, 0);
- array[startingIndex++] = value[0];
- array[startingIndex++] = value[1];
- array[startingIndex++] = value[2];
- array[startingIndex++] = value[3];
- array[startingIndex++] = value[4];
- array[startingIndex++] = value[5];
- array[startingIndex++] = value[6];
- array[startingIndex++] = value[7];
- array[startingIndex++] = value[8];
- array[startingIndex++] = value[9];
- array[startingIndex++] = value[10];
- array[startingIndex++] = value[11];
- array[startingIndex++] = value[12];
- array[startingIndex++] = value[13];
- array[startingIndex++] = value[14];
- array[startingIndex] = value[15];
- return array;
- };
- /**
- * Retrieves an instance from a packed array.
- *
- * @param {Number[]} array The packed array.
- * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.
- * @param {Matrix4} [result] The object into which to store the result.
- * @returns {Matrix4} The modified result parameter or a new Matrix4 instance if one was not provided.
- */
- Matrix4.unpack = function (array, startingIndex, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.defined("array", array);
- //>>includeEnd('debug');
- startingIndex = when.defaultValue(startingIndex, 0);
- if (!when.defined(result)) {
- result = new Matrix4();
- }
- result[0] = array[startingIndex++];
- result[1] = array[startingIndex++];
- result[2] = array[startingIndex++];
- result[3] = array[startingIndex++];
- result[4] = array[startingIndex++];
- result[5] = array[startingIndex++];
- result[6] = array[startingIndex++];
- result[7] = array[startingIndex++];
- result[8] = array[startingIndex++];
- result[9] = array[startingIndex++];
- result[10] = array[startingIndex++];
- result[11] = array[startingIndex++];
- result[12] = array[startingIndex++];
- result[13] = array[startingIndex++];
- result[14] = array[startingIndex++];
- result[15] = array[startingIndex];
- return result;
- };
- /**
- * Duplicates a Matrix4 instance.
- *
- * @param {Matrix4} matrix The matrix to duplicate.
- * @param {Matrix4} [result] The object onto which to store the result.
- * @returns {Matrix4} The modified result parameter or a new Matrix4 instance if one was not provided. (Returns undefined if matrix is undefined)
- */
- Matrix4.clone = function (matrix, result) {
- if (!when.defined(matrix)) {
- return undefined;
- }
- if (!when.defined(result)) {
- return new Matrix4(
- matrix[0],
- matrix[4],
- matrix[8],
- matrix[12],
- matrix[1],
- matrix[5],
- matrix[9],
- matrix[13],
- matrix[2],
- matrix[6],
- matrix[10],
- matrix[14],
- matrix[3],
- matrix[7],
- matrix[11],
- matrix[15]
- );
- }
- result[0] = matrix[0];
- result[1] = matrix[1];
- result[2] = matrix[2];
- result[3] = matrix[3];
- result[4] = matrix[4];
- result[5] = matrix[5];
- result[6] = matrix[6];
- result[7] = matrix[7];
- result[8] = matrix[8];
- result[9] = matrix[9];
- result[10] = matrix[10];
- result[11] = matrix[11];
- result[12] = matrix[12];
- result[13] = matrix[13];
- result[14] = matrix[14];
- result[15] = matrix[15];
- return result;
- };
- /**
- * Creates a Matrix4 from 16 consecutive elements in an array.
- * @function
- *
- * @param {Number[]} array The array whose 16 consecutive elements correspond to the positions of the matrix. Assumes column-major order.
- * @param {Number} [startingIndex=0] The offset into the array of the first element, which corresponds to first column first row position in the matrix.
- * @param {Matrix4} [result] The object onto which to store the result.
- * @returns {Matrix4} The modified result parameter or a new Matrix4 instance if one was not provided.
- *
- * @example
- * // Create the Matrix4:
- * // [1.0, 2.0, 3.0, 4.0]
- * // [1.0, 2.0, 3.0, 4.0]
- * // [1.0, 2.0, 3.0, 4.0]
- * // [1.0, 2.0, 3.0, 4.0]
- *
- * var v = [1.0, 1.0, 1.0, 1.0, 2.0, 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, 4.0];
- * var m = Cesium.Matrix4.fromArray(v);
- *
- * // Create same Matrix4 with using an offset into an array
- * var v2 = [0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 2.0, 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, 4.0];
- * var m2 = Cesium.Matrix4.fromArray(v2, 2);
- */
- Matrix4.fromArray = Matrix4.unpack;
- /**
- * Computes a Matrix4 instance from a column-major order array.
- *
- * @param {Number[]} values The column-major order array.
- * @param {Matrix4} [result] The object in which the result will be stored, if undefined a new instance will be created.
- * @returns {Matrix4} The modified result parameter, or a new Matrix4 instance if one was not provided.
- */
- Matrix4.fromColumnMajorArray = function (values, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.defined("values", values);
- //>>includeEnd('debug');
- return Matrix4.clone(values, result);
- };
- /**
- * Computes a Matrix4 instance from a row-major order array.
- * The resulting matrix will be in column-major order.
- *
- * @param {Number[]} values The row-major order array.
- * @param {Matrix4} [result] The object in which the result will be stored, if undefined a new instance will be created.
- * @returns {Matrix4} The modified result parameter, or a new Matrix4 instance if one was not provided.
- */
- Matrix4.fromRowMajorArray = function (values, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.defined("values", values);
- //>>includeEnd('debug');
- if (!when.defined(result)) {
- return new Matrix4(
- values[0],
- values[1],
- values[2],
- values[3],
- values[4],
- values[5],
- values[6],
- values[7],
- values[8],
- values[9],
- values[10],
- values[11],
- values[12],
- values[13],
- values[14],
- values[15]
- );
- }
- result[0] = values[0];
- result[1] = values[4];
- result[2] = values[8];
- result[3] = values[12];
- result[4] = values[1];
- result[5] = values[5];
- result[6] = values[9];
- result[7] = values[13];
- result[8] = values[2];
- result[9] = values[6];
- result[10] = values[10];
- result[11] = values[14];
- result[12] = values[3];
- result[13] = values[7];
- result[14] = values[11];
- result[15] = values[15];
- return result;
- };
- /**
- * Computes a Matrix4 instance from a Matrix3 representing the rotation
- * and a Cartesian3 representing the translation.
- *
- * @param {Matrix3} rotation The upper left portion of the matrix representing the rotation.
- * @param {Cartesian3} [translation=Cartesian3.ZERO] The upper right portion of the matrix representing the translation.
- * @param {Matrix4} [result] The object in which the result will be stored, if undefined a new instance will be created.
- * @returns {Matrix4} The modified result parameter, or a new Matrix4 instance if one was not provided.
- */
- Matrix4.fromRotationTranslation = function (rotation, translation, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("rotation", rotation);
- //>>includeEnd('debug');
- translation = when.defaultValue(translation, Cartesian2.Cartesian3.ZERO);
- if (!when.defined(result)) {
- return new Matrix4(
- rotation[0],
- rotation[3],
- rotation[6],
- translation.x,
- rotation[1],
- rotation[4],
- rotation[7],
- translation.y,
- rotation[2],
- rotation[5],
- rotation[8],
- translation.z,
- 0.0,
- 0.0,
- 0.0,
- 1.0
- );
- }
- result[0] = rotation[0];
- result[1] = rotation[1];
- result[2] = rotation[2];
- result[3] = 0.0;
- result[4] = rotation[3];
- result[5] = rotation[4];
- result[6] = rotation[5];
- result[7] = 0.0;
- result[8] = rotation[6];
- result[9] = rotation[7];
- result[10] = rotation[8];
- result[11] = 0.0;
- result[12] = translation.x;
- result[13] = translation.y;
- result[14] = translation.z;
- result[15] = 1.0;
- return result;
- };
- /**
- * Computes a Matrix4 instance from a translation, rotation, and scale (TRS)
- * representation with the rotation represented as a quaternion.
- *
- * @param {Cartesian3} translation The translation transformation.
- * @param {Quaternion} rotation The rotation transformation.
- * @param {Cartesian3} scale The non-uniform scale transformation.
- * @param {Matrix4} [result] The object in which the result will be stored, if undefined a new instance will be created.
- * @returns {Matrix4} The modified result parameter, or a new Matrix4 instance if one was not provided.
- *
- * @example
- * var result = Cesium.Matrix4.fromTranslationQuaternionRotationScale(
- * new Cesium.Cartesian3(1.0, 2.0, 3.0), // translation
- * Cesium.Quaternion.IDENTITY, // rotation
- * new Cesium.Cartesian3(7.0, 8.0, 9.0), // scale
- * result);
- */
- Matrix4.fromTranslationQuaternionRotationScale = function (
- translation,
- rotation,
- scale,
- result
- ) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("translation", translation);
- Check.Check.typeOf.object("rotation", rotation);
- Check.Check.typeOf.object("scale", scale);
- //>>includeEnd('debug');
- if (!when.defined(result)) {
- result = new Matrix4();
- }
- var scaleX = scale.x;
- var scaleY = scale.y;
- var scaleZ = scale.z;
- var x2 = rotation.x * rotation.x;
- var xy = rotation.x * rotation.y;
- var xz = rotation.x * rotation.z;
- var xw = rotation.x * rotation.w;
- var y2 = rotation.y * rotation.y;
- var yz = rotation.y * rotation.z;
- var yw = rotation.y * rotation.w;
- var z2 = rotation.z * rotation.z;
- var zw = rotation.z * rotation.w;
- var w2 = rotation.w * rotation.w;
- var m00 = x2 - y2 - z2 + w2;
- var m01 = 2.0 * (xy - zw);
- var m02 = 2.0 * (xz + yw);
- var m10 = 2.0 * (xy + zw);
- var m11 = -x2 + y2 - z2 + w2;
- var m12 = 2.0 * (yz - xw);
- var m20 = 2.0 * (xz - yw);
- var m21 = 2.0 * (yz + xw);
- var m22 = -x2 - y2 + z2 + w2;
- result[0] = m00 * scaleX;
- result[1] = m10 * scaleX;
- result[2] = m20 * scaleX;
- result[3] = 0.0;
- result[4] = m01 * scaleY;
- result[5] = m11 * scaleY;
- result[6] = m21 * scaleY;
- result[7] = 0.0;
- result[8] = m02 * scaleZ;
- result[9] = m12 * scaleZ;
- result[10] = m22 * scaleZ;
- result[11] = 0.0;
- result[12] = translation.x;
- result[13] = translation.y;
- result[14] = translation.z;
- result[15] = 1.0;
- return result;
- };
- /**
- * Creates a Matrix4 instance from a {@link TranslationRotationScale} instance.
- *
- * @param {TranslationRotationScale} translationRotationScale The instance.
- * @param {Matrix4} [result] The object in which the result will be stored, if undefined a new instance will be created.
- * @returns {Matrix4} The modified result parameter, or a new Matrix4 instance if one was not provided.
- */
- Matrix4.fromTranslationRotationScale = function (
- translationRotationScale,
- result
- ) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("translationRotationScale", translationRotationScale);
- //>>includeEnd('debug');
- return Matrix4.fromTranslationQuaternionRotationScale(
- translationRotationScale.translation,
- translationRotationScale.rotation,
- translationRotationScale.scale,
- result
- );
- };
- /**
- * Creates a Matrix4 instance from a Cartesian3 representing the translation.
- *
- * @param {Cartesian3} translation The upper right portion of the matrix representing the translation.
- * @param {Matrix4} [result] The object in which the result will be stored, if undefined a new instance will be created.
- * @returns {Matrix4} The modified result parameter, or a new Matrix4 instance if one was not provided.
- *
- * @see Matrix4.multiplyByTranslation
- */
- Matrix4.fromTranslation = function (translation, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("translation", translation);
- //>>includeEnd('debug');
- return Matrix4.fromRotationTranslation(Matrix3.IDENTITY, translation, result);
- };
- /**
- * Computes a Matrix4 instance representing a non-uniform scale.
- *
- * @param {Cartesian3} scale The x, y, and z scale factors.
- * @param {Matrix4} [result] The object in which the result will be stored, if undefined a new instance will be created.
- * @returns {Matrix4} The modified result parameter, or a new Matrix4 instance if one was not provided.
- *
- * @example
- * // Creates
- * // [7.0, 0.0, 0.0, 0.0]
- * // [0.0, 8.0, 0.0, 0.0]
- * // [0.0, 0.0, 9.0, 0.0]
- * // [0.0, 0.0, 0.0, 1.0]
- * var m = Cesium.Matrix4.fromScale(new Cesium.Cartesian3(7.0, 8.0, 9.0));
- */
- Matrix4.fromScale = function (scale, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("scale", scale);
- //>>includeEnd('debug');
- if (!when.defined(result)) {
- return new Matrix4(
- scale.x,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- scale.y,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- scale.z,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- 1.0
- );
- }
- result[0] = scale.x;
- result[1] = 0.0;
- result[2] = 0.0;
- result[3] = 0.0;
- result[4] = 0.0;
- result[5] = scale.y;
- result[6] = 0.0;
- result[7] = 0.0;
- result[8] = 0.0;
- result[9] = 0.0;
- result[10] = scale.z;
- result[11] = 0.0;
- result[12] = 0.0;
- result[13] = 0.0;
- result[14] = 0.0;
- result[15] = 1.0;
- return result;
- };
- /**
- * Computes a Matrix4 instance representing a uniform scale.
- *
- * @param {Number} scale The uniform scale factor.
- * @param {Matrix4} [result] The object in which the result will be stored, if undefined a new instance will be created.
- * @returns {Matrix4} The modified result parameter, or a new Matrix4 instance if one was not provided.
- *
- * @example
- * // Creates
- * // [2.0, 0.0, 0.0, 0.0]
- * // [0.0, 2.0, 0.0, 0.0]
- * // [0.0, 0.0, 2.0, 0.0]
- * // [0.0, 0.0, 0.0, 1.0]
- * var m = Cesium.Matrix4.fromUniformScale(2.0);
- */
- Matrix4.fromUniformScale = function (scale, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.number("scale", scale);
- //>>includeEnd('debug');
- if (!when.defined(result)) {
- return new Matrix4(
- scale,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- scale,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- scale,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- 1.0
- );
- }
- result[0] = scale;
- result[1] = 0.0;
- result[2] = 0.0;
- result[3] = 0.0;
- result[4] = 0.0;
- result[5] = scale;
- result[6] = 0.0;
- result[7] = 0.0;
- result[8] = 0.0;
- result[9] = 0.0;
- result[10] = scale;
- result[11] = 0.0;
- result[12] = 0.0;
- result[13] = 0.0;
- result[14] = 0.0;
- result[15] = 1.0;
- return result;
- };
- var fromCameraF = new Cartesian2.Cartesian3();
- var fromCameraR = new Cartesian2.Cartesian3();
- var fromCameraU = new Cartesian2.Cartesian3();
- /**
- * Computes a Matrix4 instance from a Camera.
- *
- * @param {Camera} camera The camera to use.
- * @param {Matrix4} [result] The object in which the result will be stored, if undefined a new instance will be created.
- * @returns {Matrix4} The modified result parameter, or a new Matrix4 instance if one was not provided.
- */
- Matrix4.fromCamera = function (camera, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("camera", camera);
- //>>includeEnd('debug');
- var position = camera.position;
- var direction = camera.direction;
- var up = camera.up;
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("camera.position", position);
- Check.Check.typeOf.object("camera.direction", direction);
- Check.Check.typeOf.object("camera.up", up);
- //>>includeEnd('debug');
- Cartesian2.Cartesian3.normalize(direction, fromCameraF);
- Cartesian2.Cartesian3.normalize(
- Cartesian2.Cartesian3.cross(fromCameraF, up, fromCameraR),
- fromCameraR
- );
- Cartesian2.Cartesian3.normalize(
- Cartesian2.Cartesian3.cross(fromCameraR, fromCameraF, fromCameraU),
- fromCameraU
- );
- var sX = fromCameraR.x;
- var sY = fromCameraR.y;
- var sZ = fromCameraR.z;
- var fX = fromCameraF.x;
- var fY = fromCameraF.y;
- var fZ = fromCameraF.z;
- var uX = fromCameraU.x;
- var uY = fromCameraU.y;
- var uZ = fromCameraU.z;
- var positionX = position.x;
- var positionY = position.y;
- var positionZ = position.z;
- var t0 = sX * -positionX + sY * -positionY + sZ * -positionZ;
- var t1 = uX * -positionX + uY * -positionY + uZ * -positionZ;
- var t2 = fX * positionX + fY * positionY + fZ * positionZ;
- // The code below this comment is an optimized
- // version of the commented lines.
- // Rather that create two matrices and then multiply,
- // we just bake in the multiplcation as part of creation.
- // var rotation = new Matrix4(
- // sX, sY, sZ, 0.0,
- // uX, uY, uZ, 0.0,
- // -fX, -fY, -fZ, 0.0,
- // 0.0, 0.0, 0.0, 1.0);
- // var translation = new Matrix4(
- // 1.0, 0.0, 0.0, -position.x,
- // 0.0, 1.0, 0.0, -position.y,
- // 0.0, 0.0, 1.0, -position.z,
- // 0.0, 0.0, 0.0, 1.0);
- // return rotation.multiply(translation);
- if (!when.defined(result)) {
- return new Matrix4(
- sX,
- sY,
- sZ,
- t0,
- uX,
- uY,
- uZ,
- t1,
- -fX,
- -fY,
- -fZ,
- t2,
- 0.0,
- 0.0,
- 0.0,
- 1.0
- );
- }
- result[0] = sX;
- result[1] = uX;
- result[2] = -fX;
- result[3] = 0.0;
- result[4] = sY;
- result[5] = uY;
- result[6] = -fY;
- result[7] = 0.0;
- result[8] = sZ;
- result[9] = uZ;
- result[10] = -fZ;
- result[11] = 0.0;
- result[12] = t0;
- result[13] = t1;
- result[14] = t2;
- result[15] = 1.0;
- return result;
- };
- /**
- * Computes a Matrix4 instance representing a perspective transformation matrix.
- *
- * @param {Number} fovY The field of view along the Y axis in radians.
- * @param {Number} aspectRatio The aspect ratio.
- * @param {Number} near The distance to the near plane in meters.
- * @param {Number} far The distance to the far plane in meters.
- * @param {Matrix4} result The object in which the result will be stored.
- * @returns {Matrix4} The modified result parameter.
- *
- * @exception {DeveloperError} fovY must be in (0, PI].
- * @exception {DeveloperError} aspectRatio must be greater than zero.
- * @exception {DeveloperError} near must be greater than zero.
- * @exception {DeveloperError} far must be greater than zero.
- */
- Matrix4.computePerspectiveFieldOfView = function (
- fovY,
- aspectRatio,
- near,
- far,
- result
- ) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.number.greaterThan("fovY", fovY, 0.0);
- Check.Check.typeOf.number.lessThan("fovY", fovY, Math.PI);
- Check.Check.typeOf.number.greaterThan("near", near, 0.0);
- Check.Check.typeOf.number.greaterThan("far", far, 0.0);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- var bottom = Math.tan(fovY * 0.5);
- var column1Row1 = 1.0 / bottom;
- var column0Row0 = column1Row1 / aspectRatio;
- var column2Row2 = (far + near) / (near - far);
- var column3Row2 = (2.0 * far * near) / (near - far);
- result[0] = column0Row0;
- result[1] = 0.0;
- result[2] = 0.0;
- result[3] = 0.0;
- result[4] = 0.0;
- result[5] = column1Row1;
- result[6] = 0.0;
- result[7] = 0.0;
- result[8] = 0.0;
- result[9] = 0.0;
- result[10] = column2Row2;
- result[11] = -1.0;
- result[12] = 0.0;
- result[13] = 0.0;
- result[14] = column3Row2;
- result[15] = 0.0;
- return result;
- };
- /**
- * Computes a Matrix4 instance representing an orthographic transformation matrix.
- *
- * @param {Number} left The number of meters to the left of the camera that will be in view.
- * @param {Number} right The number of meters to the right of the camera that will be in view.
- * @param {Number} bottom The number of meters below of the camera that will be in view.
- * @param {Number} top The number of meters above of the camera that will be in view.
- * @param {Number} near The distance to the near plane in meters.
- * @param {Number} far The distance to the far plane in meters.
- * @param {Matrix4} result The object in which the result will be stored.
- * @returns {Matrix4} The modified result parameter.
- */
- Matrix4.computeOrthographicOffCenter = function (
- left,
- right,
- bottom,
- top,
- near,
- far,
- result
- ) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.number("left", left);
- Check.Check.typeOf.number("right", right);
- Check.Check.typeOf.number("bottom", bottom);
- Check.Check.typeOf.number("top", top);
- Check.Check.typeOf.number("near", near);
- Check.Check.typeOf.number("far", far);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- var a = 1.0 / (right - left);
- var b = 1.0 / (top - bottom);
- var c = 1.0 / (far - near);
- var tx = -(right + left) * a;
- var ty = -(top + bottom) * b;
- var tz = -(far + near) * c;
- a *= 2.0;
- b *= 2.0;
- c *= -2.0;
- result[0] = a;
- result[1] = 0.0;
- result[2] = 0.0;
- result[3] = 0.0;
- result[4] = 0.0;
- result[5] = b;
- result[6] = 0.0;
- result[7] = 0.0;
- result[8] = 0.0;
- result[9] = 0.0;
- result[10] = c;
- result[11] = 0.0;
- result[12] = tx;
- result[13] = ty;
- result[14] = tz;
- result[15] = 1.0;
- return result;
- };
- /**
- * Computes a Matrix4 instance representing an off center perspective transformation.
- *
- * @param {Number} left The number of meters to the left of the camera that will be in view.
- * @param {Number} right The number of meters to the right of the camera that will be in view.
- * @param {Number} bottom The number of meters below of the camera that will be in view.
- * @param {Number} top The number of meters above of the camera that will be in view.
- * @param {Number} near The distance to the near plane in meters.
- * @param {Number} far The distance to the far plane in meters.
- * @param {Matrix4} result The object in which the result will be stored.
- * @returns {Matrix4} The modified result parameter.
- */
- Matrix4.computePerspectiveOffCenter = function (
- left,
- right,
- bottom,
- top,
- near,
- far,
- result
- ) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.number("left", left);
- Check.Check.typeOf.number("right", right);
- Check.Check.typeOf.number("bottom", bottom);
- Check.Check.typeOf.number("top", top);
- Check.Check.typeOf.number("near", near);
- Check.Check.typeOf.number("far", far);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- var column0Row0 = (2.0 * near) / (right - left);
- var column1Row1 = (2.0 * near) / (top - bottom);
- var column2Row0 = (right + left) / (right - left);
- var column2Row1 = (top + bottom) / (top - bottom);
- var column2Row2 = -(far + near) / (far - near);
- var column2Row3 = -1.0;
- var column3Row2 = (-2.0 * far * near) / (far - near);
- result[0] = column0Row0;
- result[1] = 0.0;
- result[2] = 0.0;
- result[3] = 0.0;
- result[4] = 0.0;
- result[5] = column1Row1;
- result[6] = 0.0;
- result[7] = 0.0;
- result[8] = column2Row0;
- result[9] = column2Row1;
- result[10] = column2Row2;
- result[11] = column2Row3;
- result[12] = 0.0;
- result[13] = 0.0;
- result[14] = column3Row2;
- result[15] = 0.0;
- return result;
- };
- /**
- * Computes a Matrix4 instance representing an infinite off center perspective transformation.
- *
- * @param {Number} left The number of meters to the left of the camera that will be in view.
- * @param {Number} right The number of meters to the right of the camera that will be in view.
- * @param {Number} bottom The number of meters below of the camera that will be in view.
- * @param {Number} top The number of meters above of the camera that will be in view.
- * @param {Number} near The distance to the near plane in meters.
- * @param {Matrix4} result The object in which the result will be stored.
- * @returns {Matrix4} The modified result parameter.
- */
- Matrix4.computeInfinitePerspectiveOffCenter = function (
- left,
- right,
- bottom,
- top,
- near,
- result
- ) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.number("left", left);
- Check.Check.typeOf.number("right", right);
- Check.Check.typeOf.number("bottom", bottom);
- Check.Check.typeOf.number("top", top);
- Check.Check.typeOf.number("near", near);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- var column0Row0 = (2.0 * near) / (right - left);
- var column1Row1 = (2.0 * near) / (top - bottom);
- var column2Row0 = (right + left) / (right - left);
- var column2Row1 = (top + bottom) / (top - bottom);
- var column2Row2 = -1.0;
- var column2Row3 = -1.0;
- var column3Row2 = -2.0 * near;
- result[0] = column0Row0;
- result[1] = 0.0;
- result[2] = 0.0;
- result[3] = 0.0;
- result[4] = 0.0;
- result[5] = column1Row1;
- result[6] = 0.0;
- result[7] = 0.0;
- result[8] = column2Row0;
- result[9] = column2Row1;
- result[10] = column2Row2;
- result[11] = column2Row3;
- result[12] = 0.0;
- result[13] = 0.0;
- result[14] = column3Row2;
- result[15] = 0.0;
- return result;
- };
- /**
- * Computes a Matrix4 instance that transforms from normalized device coordinates to window coordinates.
- *
- * @param {Object} [viewport = { x : 0.0, y : 0.0, width : 0.0, height : 0.0 }] The viewport's corners as shown in Example 1.
- * @param {Number} [nearDepthRange=0.0] The near plane distance in window coordinates.
- * @param {Number} [farDepthRange=1.0] The far plane distance in window coordinates.
- * @param {Matrix4} [result] The object in which the result will be stored.
- * @returns {Matrix4} The modified result parameter.
- *
- * @example
- * // Create viewport transformation using an explicit viewport and depth range.
- * var m = Cesium.Matrix4.computeViewportTransformation({
- * x : 0.0,
- * y : 0.0,
- * width : 1024.0,
- * height : 768.0
- * }, 0.0, 1.0, new Cesium.Matrix4());
- */
- Matrix4.computeViewportTransformation = function (
- viewport,
- nearDepthRange,
- farDepthRange,
- result
- ) {
- if (!when.defined(result)) {
- result = new Matrix4();
- }
- viewport = when.defaultValue(viewport, when.defaultValue.EMPTY_OBJECT);
- var x = when.defaultValue(viewport.x, 0.0);
- var y = when.defaultValue(viewport.y, 0.0);
- var width = when.defaultValue(viewport.width, 0.0);
- var height = when.defaultValue(viewport.height, 0.0);
- nearDepthRange = when.defaultValue(nearDepthRange, 0.0);
- farDepthRange = when.defaultValue(farDepthRange, 1.0);
- var halfWidth = width * 0.5;
- var halfHeight = height * 0.5;
- var halfDepth = (farDepthRange - nearDepthRange) * 0.5;
- var column0Row0 = halfWidth;
- var column1Row1 = halfHeight;
- var column2Row2 = halfDepth;
- var column3Row0 = x + halfWidth;
- var column3Row1 = y + halfHeight;
- var column3Row2 = nearDepthRange + halfDepth;
- var column3Row3 = 1.0;
- result[0] = column0Row0;
- result[1] = 0.0;
- result[2] = 0.0;
- result[3] = 0.0;
- result[4] = 0.0;
- result[5] = column1Row1;
- result[6] = 0.0;
- result[7] = 0.0;
- result[8] = 0.0;
- result[9] = 0.0;
- result[10] = column2Row2;
- result[11] = 0.0;
- result[12] = column3Row0;
- result[13] = column3Row1;
- result[14] = column3Row2;
- result[15] = column3Row3;
- return result;
- };
- /**
- * Computes a Matrix4 instance that transforms from world space to view space.
- *
- * @param {Cartesian3} position The position of the camera.
- * @param {Cartesian3} direction The forward direction.
- * @param {Cartesian3} up The up direction.
- * @param {Cartesian3} right The right direction.
- * @param {Matrix4} result The object in which the result will be stored.
- * @returns {Matrix4} The modified result parameter.
- */
- Matrix4.computeView = function (position, direction, up, right, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("position", position);
- Check.Check.typeOf.object("direction", direction);
- Check.Check.typeOf.object("up", up);
- Check.Check.typeOf.object("right", right);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- result[0] = right.x;
- result[1] = up.x;
- result[2] = -direction.x;
- result[3] = 0.0;
- result[4] = right.y;
- result[5] = up.y;
- result[6] = -direction.y;
- result[7] = 0.0;
- result[8] = right.z;
- result[9] = up.z;
- result[10] = -direction.z;
- result[11] = 0.0;
- result[12] = -Cartesian2.Cartesian3.dot(right, position);
- result[13] = -Cartesian2.Cartesian3.dot(up, position);
- result[14] = Cartesian2.Cartesian3.dot(direction, position);
- result[15] = 1.0;
- return result;
- };
- /**
- * Computes an Array from the provided Matrix4 instance.
- * The array will be in column-major order.
- *
- * @param {Matrix4} matrix The matrix to use..
- * @param {Number[]} [result] The Array onto which to store the result.
- * @returns {Number[]} The modified Array parameter or a new Array instance if one was not provided.
- *
- * @example
- * //create an array from an instance of Matrix4
- * // m = [10.0, 14.0, 18.0, 22.0]
- * // [11.0, 15.0, 19.0, 23.0]
- * // [12.0, 16.0, 20.0, 24.0]
- * // [13.0, 17.0, 21.0, 25.0]
- * var a = Cesium.Matrix4.toArray(m);
- *
- * // m remains the same
- * //creates a = [10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0]
- */
- Matrix4.toArray = function (matrix, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- //>>includeEnd('debug');
- if (!when.defined(result)) {
- return [
- matrix[0],
- matrix[1],
- matrix[2],
- matrix[3],
- matrix[4],
- matrix[5],
- matrix[6],
- matrix[7],
- matrix[8],
- matrix[9],
- matrix[10],
- matrix[11],
- matrix[12],
- matrix[13],
- matrix[14],
- matrix[15],
- ];
- }
- result[0] = matrix[0];
- result[1] = matrix[1];
- result[2] = matrix[2];
- result[3] = matrix[3];
- result[4] = matrix[4];
- result[5] = matrix[5];
- result[6] = matrix[6];
- result[7] = matrix[7];
- result[8] = matrix[8];
- result[9] = matrix[9];
- result[10] = matrix[10];
- result[11] = matrix[11];
- result[12] = matrix[12];
- result[13] = matrix[13];
- result[14] = matrix[14];
- result[15] = matrix[15];
- return result;
- };
- /**
- * Computes the array index of the element at the provided row and column.
- *
- * @param {Number} row The zero-based index of the row.
- * @param {Number} column The zero-based index of the column.
- * @returns {Number} The index of the element at the provided row and column.
- *
- * @exception {DeveloperError} row must be 0, 1, 2, or 3.
- * @exception {DeveloperError} column must be 0, 1, 2, or 3.
- *
- * @example
- * var myMatrix = new Cesium.Matrix4();
- * var column1Row0Index = Cesium.Matrix4.getElementIndex(1, 0);
- * var column1Row0 = myMatrix[column1Row0Index];
- * myMatrix[column1Row0Index] = 10.0;
- */
- Matrix4.getElementIndex = function (column, row) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.number.greaterThanOrEquals("row", row, 0);
- Check.Check.typeOf.number.lessThanOrEquals("row", row, 3);
- Check.Check.typeOf.number.greaterThanOrEquals("column", column, 0);
- Check.Check.typeOf.number.lessThanOrEquals("column", column, 3);
- //>>includeEnd('debug');
- return column * 4 + row;
- };
- /**
- * Retrieves a copy of the matrix column at the provided index as a Cartesian4 instance.
- *
- * @param {Matrix4} matrix The matrix to use.
- * @param {Number} index The zero-based index of the column to retrieve.
- * @param {Cartesian4} result The object onto which to store the result.
- * @returns {Cartesian4} The modified result parameter.
- *
- * @exception {DeveloperError} index must be 0, 1, 2, or 3.
- *
- * @example
- * //returns a Cartesian4 instance with values from the specified column
- * // m = [10.0, 11.0, 12.0, 13.0]
- * // [14.0, 15.0, 16.0, 17.0]
- * // [18.0, 19.0, 20.0, 21.0]
- * // [22.0, 23.0, 24.0, 25.0]
- *
- * //Example 1: Creates an instance of Cartesian
- * var a = Cesium.Matrix4.getColumn(m, 2, new Cesium.Cartesian4());
- *
- * @example
- * //Example 2: Sets values for Cartesian instance
- * var a = new Cesium.Cartesian4();
- * Cesium.Matrix4.getColumn(m, 2, a);
- *
- * // a.x = 12.0; a.y = 16.0; a.z = 20.0; a.w = 24.0;
- */
- Matrix4.getColumn = function (matrix, index, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- Check.Check.typeOf.number.greaterThanOrEquals("index", index, 0);
- Check.Check.typeOf.number.lessThanOrEquals("index", index, 3);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- var startIndex = index * 4;
- var x = matrix[startIndex];
- var y = matrix[startIndex + 1];
- var z = matrix[startIndex + 2];
- var w = matrix[startIndex + 3];
- result.x = x;
- result.y = y;
- result.z = z;
- result.w = w;
- return result;
- };
- /**
- * Computes a new matrix that replaces the specified column in the provided matrix with the provided Cartesian4 instance.
- *
- * @param {Matrix4} matrix The matrix to use.
- * @param {Number} index The zero-based index of the column to set.
- * @param {Cartesian4} cartesian The Cartesian whose values will be assigned to the specified column.
- * @param {Matrix4} result The object onto which to store the result.
- * @returns {Matrix4} The modified result parameter.
- *
- * @exception {DeveloperError} index must be 0, 1, 2, or 3.
- *
- * @example
- * //creates a new Matrix4 instance with new column values from the Cartesian4 instance
- * // m = [10.0, 11.0, 12.0, 13.0]
- * // [14.0, 15.0, 16.0, 17.0]
- * // [18.0, 19.0, 20.0, 21.0]
- * // [22.0, 23.0, 24.0, 25.0]
- *
- * var a = Cesium.Matrix4.setColumn(m, 2, new Cesium.Cartesian4(99.0, 98.0, 97.0, 96.0), new Cesium.Matrix4());
- *
- * // m remains the same
- * // a = [10.0, 11.0, 99.0, 13.0]
- * // [14.0, 15.0, 98.0, 17.0]
- * // [18.0, 19.0, 97.0, 21.0]
- * // [22.0, 23.0, 96.0, 25.0]
- */
- Matrix4.setColumn = function (matrix, index, cartesian, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- Check.Check.typeOf.number.greaterThanOrEquals("index", index, 0);
- Check.Check.typeOf.number.lessThanOrEquals("index", index, 3);
- Check.Check.typeOf.object("cartesian", cartesian);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- result = Matrix4.clone(matrix, result);
- var startIndex = index * 4;
- result[startIndex] = cartesian.x;
- result[startIndex + 1] = cartesian.y;
- result[startIndex + 2] = cartesian.z;
- result[startIndex + 3] = cartesian.w;
- return result;
- };
- /**
- * Computes a new matrix that replaces the translation in the rightmost column of the provided
- * matrix with the provided translation. This assumes the matrix is an affine transformation
- *
- * @param {Matrix4} matrix The matrix to use.
- * @param {Cartesian3} translation The translation that replaces the translation of the provided matrix.
- * @param {Matrix4} result The object onto which to store the result.
- * @returns {Matrix4} The modified result parameter.
- */
- Matrix4.setTranslation = function (matrix, translation, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- Check.Check.typeOf.object("translation", translation);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- result[0] = matrix[0];
- result[1] = matrix[1];
- result[2] = matrix[2];
- result[3] = matrix[3];
- result[4] = matrix[4];
- result[5] = matrix[5];
- result[6] = matrix[6];
- result[7] = matrix[7];
- result[8] = matrix[8];
- result[9] = matrix[9];
- result[10] = matrix[10];
- result[11] = matrix[11];
- result[12] = translation.x;
- result[13] = translation.y;
- result[14] = translation.z;
- result[15] = matrix[15];
- return result;
- };
- var scaleScratch = new Cartesian2.Cartesian3();
- /**
- * Computes a new matrix that replaces the scale with the provided scale. This assumes the matrix is an affine transformation
- *
- * @param {Matrix4} matrix The matrix to use.
- * @param {Cartesian3} scale The scale that replaces the scale of the provided matrix.
- * @param {Matrix4} result The object onto which to store the result.
- * @returns {Matrix4} The modified result parameter.
- */
- Matrix4.setScale = function (matrix, scale, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- Check.Check.typeOf.object("scale", scale);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- var existingScale = Matrix4.getScale(matrix, scaleScratch);
- var newScale = Cartesian2.Cartesian3.divideComponents(
- scale,
- existingScale,
- scaleScratch
- );
- return Matrix4.multiplyByScale(matrix, newScale, result);
- };
- /**
- * Retrieves a copy of the matrix row at the provided index as a Cartesian4 instance.
- *
- * @param {Matrix4} matrix The matrix to use.
- * @param {Number} index The zero-based index of the row to retrieve.
- * @param {Cartesian4} result The object onto which to store the result.
- * @returns {Cartesian4} The modified result parameter.
- *
- * @exception {DeveloperError} index must be 0, 1, 2, or 3.
- *
- * @example
- * //returns a Cartesian4 instance with values from the specified column
- * // m = [10.0, 11.0, 12.0, 13.0]
- * // [14.0, 15.0, 16.0, 17.0]
- * // [18.0, 19.0, 20.0, 21.0]
- * // [22.0, 23.0, 24.0, 25.0]
- *
- * //Example 1: Returns an instance of Cartesian
- * var a = Cesium.Matrix4.getRow(m, 2, new Cesium.Cartesian4());
- *
- * @example
- * //Example 2: Sets values for a Cartesian instance
- * var a = new Cesium.Cartesian4();
- * Cesium.Matrix4.getRow(m, 2, a);
- *
- * // a.x = 18.0; a.y = 19.0; a.z = 20.0; a.w = 21.0;
- */
- Matrix4.getRow = function (matrix, index, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- Check.Check.typeOf.number.greaterThanOrEquals("index", index, 0);
- Check.Check.typeOf.number.lessThanOrEquals("index", index, 3);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- var x = matrix[index];
- var y = matrix[index + 4];
- var z = matrix[index + 8];
- var w = matrix[index + 12];
- result.x = x;
- result.y = y;
- result.z = z;
- result.w = w;
- return result;
- };
- /**
- * Computes a new matrix that replaces the specified row in the provided matrix with the provided Cartesian4 instance.
- *
- * @param {Matrix4} matrix The matrix to use.
- * @param {Number} index The zero-based index of the row to set.
- * @param {Cartesian4} cartesian The Cartesian whose values will be assigned to the specified row.
- * @param {Matrix4} result The object onto which to store the result.
- * @returns {Matrix4} The modified result parameter.
- *
- * @exception {DeveloperError} index must be 0, 1, 2, or 3.
- *
- * @example
- * //create a new Matrix4 instance with new row values from the Cartesian4 instance
- * // m = [10.0, 11.0, 12.0, 13.0]
- * // [14.0, 15.0, 16.0, 17.0]
- * // [18.0, 19.0, 20.0, 21.0]
- * // [22.0, 23.0, 24.0, 25.0]
- *
- * var a = Cesium.Matrix4.setRow(m, 2, new Cesium.Cartesian4(99.0, 98.0, 97.0, 96.0), new Cesium.Matrix4());
- *
- * // m remains the same
- * // a = [10.0, 11.0, 12.0, 13.0]
- * // [14.0, 15.0, 16.0, 17.0]
- * // [99.0, 98.0, 97.0, 96.0]
- * // [22.0, 23.0, 24.0, 25.0]
- */
- Matrix4.setRow = function (matrix, index, cartesian, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- Check.Check.typeOf.number.greaterThanOrEquals("index", index, 0);
- Check.Check.typeOf.number.lessThanOrEquals("index", index, 3);
- Check.Check.typeOf.object("cartesian", cartesian);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- result = Matrix4.clone(matrix, result);
- result[index] = cartesian.x;
- result[index + 4] = cartesian.y;
- result[index + 8] = cartesian.z;
- result[index + 12] = cartesian.w;
- return result;
- };
- var scratchColumn$1 = new Cartesian2.Cartesian3();
- /**
- * Extracts the non-uniform scale assuming the matrix is an affine transformation.
- *
- * @param {Matrix4} matrix The matrix.
- * @param {Cartesian3} result The object onto which to store the result.
- * @returns {Cartesian3} The modified result parameter
- */
- Matrix4.getScale = function (matrix, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- result.x = Cartesian2.Cartesian3.magnitude(
- Cartesian2.Cartesian3.fromElements(matrix[0], matrix[1], matrix[2], scratchColumn$1)
- );
- result.y = Cartesian2.Cartesian3.magnitude(
- Cartesian2.Cartesian3.fromElements(matrix[4], matrix[5], matrix[6], scratchColumn$1)
- );
- result.z = Cartesian2.Cartesian3.magnitude(
- Cartesian2.Cartesian3.fromElements(matrix[8], matrix[9], matrix[10], scratchColumn$1)
- );
- return result;
- };
- var scratchScale$1 = new Cartesian2.Cartesian3();
- /**
- * Computes the maximum scale assuming the matrix is an affine transformation.
- * The maximum scale is the maximum length of the column vectors in the upper-left
- * 3x3 matrix.
- *
- * @param {Matrix4} matrix The matrix.
- * @returns {Number} The maximum scale.
- */
- Matrix4.getMaximumScale = function (matrix) {
- Matrix4.getScale(matrix, scratchScale$1);
- return Cartesian2.Cartesian3.maximumComponent(scratchScale$1);
- };
- /**
- * Computes the product of two matrices.
- *
- * @param {Matrix4} left The first matrix.
- * @param {Matrix4} right The second matrix.
- * @param {Matrix4} result The object onto which to store the result.
- * @returns {Matrix4} The modified result parameter.
- */
- Matrix4.multiply = function (left, right, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("left", left);
- Check.Check.typeOf.object("right", right);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- var left0 = left[0];
- var left1 = left[1];
- var left2 = left[2];
- var left3 = left[3];
- var left4 = left[4];
- var left5 = left[5];
- var left6 = left[6];
- var left7 = left[7];
- var left8 = left[8];
- var left9 = left[9];
- var left10 = left[10];
- var left11 = left[11];
- var left12 = left[12];
- var left13 = left[13];
- var left14 = left[14];
- var left15 = left[15];
- var right0 = right[0];
- var right1 = right[1];
- var right2 = right[2];
- var right3 = right[3];
- var right4 = right[4];
- var right5 = right[5];
- var right6 = right[6];
- var right7 = right[7];
- var right8 = right[8];
- var right9 = right[9];
- var right10 = right[10];
- var right11 = right[11];
- var right12 = right[12];
- var right13 = right[13];
- var right14 = right[14];
- var right15 = right[15];
- var column0Row0 =
- left0 * right0 + left4 * right1 + left8 * right2 + left12 * right3;
- var column0Row1 =
- left1 * right0 + left5 * right1 + left9 * right2 + left13 * right3;
- var column0Row2 =
- left2 * right0 + left6 * right1 + left10 * right2 + left14 * right3;
- var column0Row3 =
- left3 * right0 + left7 * right1 + left11 * right2 + left15 * right3;
- var column1Row0 =
- left0 * right4 + left4 * right5 + left8 * right6 + left12 * right7;
- var column1Row1 =
- left1 * right4 + left5 * right5 + left9 * right6 + left13 * right7;
- var column1Row2 =
- left2 * right4 + left6 * right5 + left10 * right6 + left14 * right7;
- var column1Row3 =
- left3 * right4 + left7 * right5 + left11 * right6 + left15 * right7;
- var column2Row0 =
- left0 * right8 + left4 * right9 + left8 * right10 + left12 * right11;
- var column2Row1 =
- left1 * right8 + left5 * right9 + left9 * right10 + left13 * right11;
- var column2Row2 =
- left2 * right8 + left6 * right9 + left10 * right10 + left14 * right11;
- var column2Row3 =
- left3 * right8 + left7 * right9 + left11 * right10 + left15 * right11;
- var column3Row0 =
- left0 * right12 + left4 * right13 + left8 * right14 + left12 * right15;
- var column3Row1 =
- left1 * right12 + left5 * right13 + left9 * right14 + left13 * right15;
- var column3Row2 =
- left2 * right12 + left6 * right13 + left10 * right14 + left14 * right15;
- var column3Row3 =
- left3 * right12 + left7 * right13 + left11 * right14 + left15 * right15;
- result[0] = column0Row0;
- result[1] = column0Row1;
- result[2] = column0Row2;
- result[3] = column0Row3;
- result[4] = column1Row0;
- result[5] = column1Row1;
- result[6] = column1Row2;
- result[7] = column1Row3;
- result[8] = column2Row0;
- result[9] = column2Row1;
- result[10] = column2Row2;
- result[11] = column2Row3;
- result[12] = column3Row0;
- result[13] = column3Row1;
- result[14] = column3Row2;
- result[15] = column3Row3;
- return result;
- };
- /**
- * Computes the sum of two matrices.
- *
- * @param {Matrix4} left The first matrix.
- * @param {Matrix4} right The second matrix.
- * @param {Matrix4} result The object onto which to store the result.
- * @returns {Matrix4} The modified result parameter.
- */
- Matrix4.add = function (left, right, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("left", left);
- Check.Check.typeOf.object("right", right);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- result[0] = left[0] + right[0];
- result[1] = left[1] + right[1];
- result[2] = left[2] + right[2];
- result[3] = left[3] + right[3];
- result[4] = left[4] + right[4];
- result[5] = left[5] + right[5];
- result[6] = left[6] + right[6];
- result[7] = left[7] + right[7];
- result[8] = left[8] + right[8];
- result[9] = left[9] + right[9];
- result[10] = left[10] + right[10];
- result[11] = left[11] + right[11];
- result[12] = left[12] + right[12];
- result[13] = left[13] + right[13];
- result[14] = left[14] + right[14];
- result[15] = left[15] + right[15];
- return result;
- };
- /**
- * Computes the difference of two matrices.
- *
- * @param {Matrix4} left The first matrix.
- * @param {Matrix4} right The second matrix.
- * @param {Matrix4} result The object onto which to store the result.
- * @returns {Matrix4} The modified result parameter.
- */
- Matrix4.subtract = function (left, right, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("left", left);
- Check.Check.typeOf.object("right", right);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- result[0] = left[0] - right[0];
- result[1] = left[1] - right[1];
- result[2] = left[2] - right[2];
- result[3] = left[3] - right[3];
- result[4] = left[4] - right[4];
- result[5] = left[5] - right[5];
- result[6] = left[6] - right[6];
- result[7] = left[7] - right[7];
- result[8] = left[8] - right[8];
- result[9] = left[9] - right[9];
- result[10] = left[10] - right[10];
- result[11] = left[11] - right[11];
- result[12] = left[12] - right[12];
- result[13] = left[13] - right[13];
- result[14] = left[14] - right[14];
- result[15] = left[15] - right[15];
- return result;
- };
- /**
- * Computes the product of two matrices assuming the matrices are
- * affine transformation matrices, where the upper left 3x3 elements
- * are a rotation matrix, and the upper three elements in the fourth
- * column are the translation. The bottom row is assumed to be [0, 0, 0, 1].
- * The matrix is not verified to be in the proper form.
- * This method is faster than computing the product for general 4x4
- * matrices using {@link Matrix4.multiply}.
- *
- * @param {Matrix4} left The first matrix.
- * @param {Matrix4} right The second matrix.
- * @param {Matrix4} result The object onto which to store the result.
- * @returns {Matrix4} The modified result parameter.
- *
- * @example
- * var m1 = new Cesium.Matrix4(1.0, 6.0, 7.0, 0.0, 2.0, 5.0, 8.0, 0.0, 3.0, 4.0, 9.0, 0.0, 0.0, 0.0, 0.0, 1.0);
- * var m2 = Cesium.Transforms.eastNorthUpToFixedFrame(new Cesium.Cartesian3(1.0, 1.0, 1.0));
- * var m3 = Cesium.Matrix4.multiplyTransformation(m1, m2, new Cesium.Matrix4());
- */
- Matrix4.multiplyTransformation = function (left, right, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("left", left);
- Check.Check.typeOf.object("right", right);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- var left0 = left[0];
- var left1 = left[1];
- var left2 = left[2];
- var left4 = left[4];
- var left5 = left[5];
- var left6 = left[6];
- var left8 = left[8];
- var left9 = left[9];
- var left10 = left[10];
- var left12 = left[12];
- var left13 = left[13];
- var left14 = left[14];
- var right0 = right[0];
- var right1 = right[1];
- var right2 = right[2];
- var right4 = right[4];
- var right5 = right[5];
- var right6 = right[6];
- var right8 = right[8];
- var right9 = right[9];
- var right10 = right[10];
- var right12 = right[12];
- var right13 = right[13];
- var right14 = right[14];
- var column0Row0 = left0 * right0 + left4 * right1 + left8 * right2;
- var column0Row1 = left1 * right0 + left5 * right1 + left9 * right2;
- var column0Row2 = left2 * right0 + left6 * right1 + left10 * right2;
- var column1Row0 = left0 * right4 + left4 * right5 + left8 * right6;
- var column1Row1 = left1 * right4 + left5 * right5 + left9 * right6;
- var column1Row2 = left2 * right4 + left6 * right5 + left10 * right6;
- var column2Row0 = left0 * right8 + left4 * right9 + left8 * right10;
- var column2Row1 = left1 * right8 + left5 * right9 + left9 * right10;
- var column2Row2 = left2 * right8 + left6 * right9 + left10 * right10;
- var column3Row0 =
- left0 * right12 + left4 * right13 + left8 * right14 + left12;
- var column3Row1 =
- left1 * right12 + left5 * right13 + left9 * right14 + left13;
- var column3Row2 =
- left2 * right12 + left6 * right13 + left10 * right14 + left14;
- result[0] = column0Row0;
- result[1] = column0Row1;
- result[2] = column0Row2;
- result[3] = 0.0;
- result[4] = column1Row0;
- result[5] = column1Row1;
- result[6] = column1Row2;
- result[7] = 0.0;
- result[8] = column2Row0;
- result[9] = column2Row1;
- result[10] = column2Row2;
- result[11] = 0.0;
- result[12] = column3Row0;
- result[13] = column3Row1;
- result[14] = column3Row2;
- result[15] = 1.0;
- return result;
- };
- /**
- * Multiplies a transformation matrix (with a bottom row of <code>[0.0, 0.0, 0.0, 1.0]</code>)
- * by a 3x3 rotation matrix. This is an optimization
- * for <code>Matrix4.multiply(m, Matrix4.fromRotationTranslation(rotation), m);</code> with less allocations and arithmetic operations.
- *
- * @param {Matrix4} matrix The matrix on the left-hand side.
- * @param {Matrix3} rotation The 3x3 rotation matrix on the right-hand side.
- * @param {Matrix4} result The object onto which to store the result.
- * @returns {Matrix4} The modified result parameter.
- *
- * @example
- * // Instead of Cesium.Matrix4.multiply(m, Cesium.Matrix4.fromRotationTranslation(rotation), m);
- * Cesium.Matrix4.multiplyByMatrix3(m, rotation, m);
- */
- Matrix4.multiplyByMatrix3 = function (matrix, rotation, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- Check.Check.typeOf.object("rotation", rotation);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- var left0 = matrix[0];
- var left1 = matrix[1];
- var left2 = matrix[2];
- var left4 = matrix[4];
- var left5 = matrix[5];
- var left6 = matrix[6];
- var left8 = matrix[8];
- var left9 = matrix[9];
- var left10 = matrix[10];
- var right0 = rotation[0];
- var right1 = rotation[1];
- var right2 = rotation[2];
- var right4 = rotation[3];
- var right5 = rotation[4];
- var right6 = rotation[5];
- var right8 = rotation[6];
- var right9 = rotation[7];
- var right10 = rotation[8];
- var column0Row0 = left0 * right0 + left4 * right1 + left8 * right2;
- var column0Row1 = left1 * right0 + left5 * right1 + left9 * right2;
- var column0Row2 = left2 * right0 + left6 * right1 + left10 * right2;
- var column1Row0 = left0 * right4 + left4 * right5 + left8 * right6;
- var column1Row1 = left1 * right4 + left5 * right5 + left9 * right6;
- var column1Row2 = left2 * right4 + left6 * right5 + left10 * right6;
- var column2Row0 = left0 * right8 + left4 * right9 + left8 * right10;
- var column2Row1 = left1 * right8 + left5 * right9 + left9 * right10;
- var column2Row2 = left2 * right8 + left6 * right9 + left10 * right10;
- result[0] = column0Row0;
- result[1] = column0Row1;
- result[2] = column0Row2;
- result[3] = 0.0;
- result[4] = column1Row0;
- result[5] = column1Row1;
- result[6] = column1Row2;
- result[7] = 0.0;
- result[8] = column2Row0;
- result[9] = column2Row1;
- result[10] = column2Row2;
- result[11] = 0.0;
- result[12] = matrix[12];
- result[13] = matrix[13];
- result[14] = matrix[14];
- result[15] = matrix[15];
- return result;
- };
- /**
- * Multiplies a transformation matrix (with a bottom row of <code>[0.0, 0.0, 0.0, 1.0]</code>)
- * by an implicit translation matrix defined by a {@link Cartesian3}. This is an optimization
- * for <code>Matrix4.multiply(m, Matrix4.fromTranslation(position), m);</code> with less allocations and arithmetic operations.
- *
- * @param {Matrix4} matrix The matrix on the left-hand side.
- * @param {Cartesian3} translation The translation on the right-hand side.
- * @param {Matrix4} result The object onto which to store the result.
- * @returns {Matrix4} The modified result parameter.
- *
- * @example
- * // Instead of Cesium.Matrix4.multiply(m, Cesium.Matrix4.fromTranslation(position), m);
- * Cesium.Matrix4.multiplyByTranslation(m, position, m);
- */
- Matrix4.multiplyByTranslation = function (matrix, translation, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- Check.Check.typeOf.object("translation", translation);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- var x = translation.x;
- var y = translation.y;
- var z = translation.z;
- var tx = x * matrix[0] + y * matrix[4] + z * matrix[8] + matrix[12];
- var ty = x * matrix[1] + y * matrix[5] + z * matrix[9] + matrix[13];
- var tz = x * matrix[2] + y * matrix[6] + z * matrix[10] + matrix[14];
- result[0] = matrix[0];
- result[1] = matrix[1];
- result[2] = matrix[2];
- result[3] = matrix[3];
- result[4] = matrix[4];
- result[5] = matrix[5];
- result[6] = matrix[6];
- result[7] = matrix[7];
- result[8] = matrix[8];
- result[9] = matrix[9];
- result[10] = matrix[10];
- result[11] = matrix[11];
- result[12] = tx;
- result[13] = ty;
- result[14] = tz;
- result[15] = matrix[15];
- return result;
- };
- var uniformScaleScratch = new Cartesian2.Cartesian3();
- /**
- * Multiplies an affine transformation matrix (with a bottom row of <code>[0.0, 0.0, 0.0, 1.0]</code>)
- * by an implicit uniform scale matrix. This is an optimization
- * for <code>Matrix4.multiply(m, Matrix4.fromUniformScale(scale), m);</code>, where
- * <code>m</code> must be an affine matrix.
- * This function performs fewer allocations and arithmetic operations.
- *
- * @param {Matrix4} matrix The affine matrix on the left-hand side.
- * @param {Number} scale The uniform scale on the right-hand side.
- * @param {Matrix4} result The object onto which to store the result.
- * @returns {Matrix4} The modified result parameter.
- *
- *
- * @example
- * // Instead of Cesium.Matrix4.multiply(m, Cesium.Matrix4.fromUniformScale(scale), m);
- * Cesium.Matrix4.multiplyByUniformScale(m, scale, m);
- *
- * @see Matrix4.fromUniformScale
- * @see Matrix4.multiplyByScale
- */
- Matrix4.multiplyByUniformScale = function (matrix, scale, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- Check.Check.typeOf.number("scale", scale);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- uniformScaleScratch.x = scale;
- uniformScaleScratch.y = scale;
- uniformScaleScratch.z = scale;
- return Matrix4.multiplyByScale(matrix, uniformScaleScratch, result);
- };
- /**
- * Multiplies an affine transformation matrix (with a bottom row of <code>[0.0, 0.0, 0.0, 1.0]</code>)
- * by an implicit non-uniform scale matrix. This is an optimization
- * for <code>Matrix4.multiply(m, Matrix4.fromUniformScale(scale), m);</code>, where
- * <code>m</code> must be an affine matrix.
- * This function performs fewer allocations and arithmetic operations.
- *
- * @param {Matrix4} matrix The affine matrix on the left-hand side.
- * @param {Cartesian3} scale The non-uniform scale on the right-hand side.
- * @param {Matrix4} result The object onto which to store the result.
- * @returns {Matrix4} The modified result parameter.
- *
- *
- * @example
- * // Instead of Cesium.Matrix4.multiply(m, Cesium.Matrix4.fromScale(scale), m);
- * Cesium.Matrix4.multiplyByScale(m, scale, m);
- *
- * @see Matrix4.fromScale
- * @see Matrix4.multiplyByUniformScale
- */
- Matrix4.multiplyByScale = function (matrix, scale, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- Check.Check.typeOf.object("scale", scale);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- var scaleX = scale.x;
- var scaleY = scale.y;
- var scaleZ = scale.z;
- // Faster than Cartesian3.equals
- if (scaleX === 1.0 && scaleY === 1.0 && scaleZ === 1.0) {
- return Matrix4.clone(matrix, result);
- }
- result[0] = scaleX * matrix[0];
- result[1] = scaleX * matrix[1];
- result[2] = scaleX * matrix[2];
- result[3] = 0.0;
- result[4] = scaleY * matrix[4];
- result[5] = scaleY * matrix[5];
- result[6] = scaleY * matrix[6];
- result[7] = 0.0;
- result[8] = scaleZ * matrix[8];
- result[9] = scaleZ * matrix[9];
- result[10] = scaleZ * matrix[10];
- result[11] = 0.0;
- result[12] = matrix[12];
- result[13] = matrix[13];
- result[14] = matrix[14];
- result[15] = 1.0;
- return result;
- };
- /**
- * Computes the product of a matrix and a column vector.
- *
- * @param {Matrix4} matrix The matrix.
- * @param {Cartesian4} cartesian The vector.
- * @param {Cartesian4} result The object onto which to store the result.
- * @returns {Cartesian4} The modified result parameter.
- */
- Matrix4.multiplyByVector = function (matrix, cartesian, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- Check.Check.typeOf.object("cartesian", cartesian);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- var vX = cartesian.x;
- var vY = cartesian.y;
- var vZ = cartesian.z;
- var vW = cartesian.w;
- var x = matrix[0] * vX + matrix[4] * vY + matrix[8] * vZ + matrix[12] * vW;
- var y = matrix[1] * vX + matrix[5] * vY + matrix[9] * vZ + matrix[13] * vW;
- var z = matrix[2] * vX + matrix[6] * vY + matrix[10] * vZ + matrix[14] * vW;
- var w = matrix[3] * vX + matrix[7] * vY + matrix[11] * vZ + matrix[15] * vW;
- result.x = x;
- result.y = y;
- result.z = z;
- result.w = w;
- return result;
- };
- /**
- * Computes the product of a matrix and a {@link Cartesian3}. This is equivalent to calling {@link Matrix4.multiplyByVector}
- * with a {@link Cartesian4} with a <code>w</code> component of zero.
- *
- * @param {Matrix4} matrix The matrix.
- * @param {Cartesian3} cartesian The point.
- * @param {Cartesian3} result The object onto which to store the result.
- * @returns {Cartesian3} The modified result parameter.
- *
- * @example
- * var p = new Cesium.Cartesian3(1.0, 2.0, 3.0);
- * var result = Cesium.Matrix4.multiplyByPointAsVector(matrix, p, new Cesium.Cartesian3());
- * // A shortcut for
- * // Cartesian3 p = ...
- * // Cesium.Matrix4.multiplyByVector(matrix, new Cesium.Cartesian4(p.x, p.y, p.z, 0.0), result);
- */
- Matrix4.multiplyByPointAsVector = function (matrix, cartesian, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- Check.Check.typeOf.object("cartesian", cartesian);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- var vX = cartesian.x;
- var vY = cartesian.y;
- var vZ = cartesian.z;
- var x = matrix[0] * vX + matrix[4] * vY + matrix[8] * vZ;
- var y = matrix[1] * vX + matrix[5] * vY + matrix[9] * vZ;
- var z = matrix[2] * vX + matrix[6] * vY + matrix[10] * vZ;
- result.x = x;
- result.y = y;
- result.z = z;
- return result;
- };
- /**
- * Computes the product of a matrix and a {@link Cartesian3}. This is equivalent to calling {@link Matrix4.multiplyByVector}
- * with a {@link Cartesian4} with a <code>w</code> component of 1, but returns a {@link Cartesian3} instead of a {@link Cartesian4}.
- *
- * @param {Matrix4} matrix The matrix.
- * @param {Cartesian3} cartesian The point.
- * @param {Cartesian3} result The object onto which to store the result.
- * @returns {Cartesian3} The modified result parameter.
- *
- * @example
- * var p = new Cesium.Cartesian3(1.0, 2.0, 3.0);
- * var result = Cesium.Matrix4.multiplyByPoint(matrix, p, new Cesium.Cartesian3());
- */
- Matrix4.multiplyByPoint = function (matrix, cartesian, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- Check.Check.typeOf.object("cartesian", cartesian);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- var vX = cartesian.x;
- var vY = cartesian.y;
- var vZ = cartesian.z;
- var x = matrix[0] * vX + matrix[4] * vY + matrix[8] * vZ + matrix[12];
- var y = matrix[1] * vX + matrix[5] * vY + matrix[9] * vZ + matrix[13];
- var z = matrix[2] * vX + matrix[6] * vY + matrix[10] * vZ + matrix[14];
- result.x = x;
- result.y = y;
- result.z = z;
- return result;
- };
- /**
- * Computes the product of a matrix and a scalar.
- *
- * @param {Matrix4} matrix The matrix.
- * @param {Number} scalar The number to multiply by.
- * @param {Matrix4} result The object onto which to store the result.
- * @returns {Matrix4} The modified result parameter.
- *
- * @example
- * //create a Matrix4 instance which is a scaled version of the supplied Matrix4
- * // m = [10.0, 11.0, 12.0, 13.0]
- * // [14.0, 15.0, 16.0, 17.0]
- * // [18.0, 19.0, 20.0, 21.0]
- * // [22.0, 23.0, 24.0, 25.0]
- *
- * var a = Cesium.Matrix4.multiplyByScalar(m, -2, new Cesium.Matrix4());
- *
- * // m remains the same
- * // a = [-20.0, -22.0, -24.0, -26.0]
- * // [-28.0, -30.0, -32.0, -34.0]
- * // [-36.0, -38.0, -40.0, -42.0]
- * // [-44.0, -46.0, -48.0, -50.0]
- */
- Matrix4.multiplyByScalar = function (matrix, scalar, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- Check.Check.typeOf.number("scalar", scalar);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- result[0] = matrix[0] * scalar;
- result[1] = matrix[1] * scalar;
- result[2] = matrix[2] * scalar;
- result[3] = matrix[3] * scalar;
- result[4] = matrix[4] * scalar;
- result[5] = matrix[5] * scalar;
- result[6] = matrix[6] * scalar;
- result[7] = matrix[7] * scalar;
- result[8] = matrix[8] * scalar;
- result[9] = matrix[9] * scalar;
- result[10] = matrix[10] * scalar;
- result[11] = matrix[11] * scalar;
- result[12] = matrix[12] * scalar;
- result[13] = matrix[13] * scalar;
- result[14] = matrix[14] * scalar;
- result[15] = matrix[15] * scalar;
- return result;
- };
- /**
- * Computes a negated copy of the provided matrix.
- *
- * @param {Matrix4} matrix The matrix to negate.
- * @param {Matrix4} result The object onto which to store the result.
- * @returns {Matrix4} The modified result parameter.
- *
- * @example
- * //create a new Matrix4 instance which is a negation of a Matrix4
- * // m = [10.0, 11.0, 12.0, 13.0]
- * // [14.0, 15.0, 16.0, 17.0]
- * // [18.0, 19.0, 20.0, 21.0]
- * // [22.0, 23.0, 24.0, 25.0]
- *
- * var a = Cesium.Matrix4.negate(m, new Cesium.Matrix4());
- *
- * // m remains the same
- * // a = [-10.0, -11.0, -12.0, -13.0]
- * // [-14.0, -15.0, -16.0, -17.0]
- * // [-18.0, -19.0, -20.0, -21.0]
- * // [-22.0, -23.0, -24.0, -25.0]
- */
- Matrix4.negate = function (matrix, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- result[0] = -matrix[0];
- result[1] = -matrix[1];
- result[2] = -matrix[2];
- result[3] = -matrix[3];
- result[4] = -matrix[4];
- result[5] = -matrix[5];
- result[6] = -matrix[6];
- result[7] = -matrix[7];
- result[8] = -matrix[8];
- result[9] = -matrix[9];
- result[10] = -matrix[10];
- result[11] = -matrix[11];
- result[12] = -matrix[12];
- result[13] = -matrix[13];
- result[14] = -matrix[14];
- result[15] = -matrix[15];
- return result;
- };
- /**
- * Computes the transpose of the provided matrix.
- *
- * @param {Matrix4} matrix The matrix to transpose.
- * @param {Matrix4} result The object onto which to store the result.
- * @returns {Matrix4} The modified result parameter.
- *
- * @example
- * //returns transpose of a Matrix4
- * // m = [10.0, 11.0, 12.0, 13.0]
- * // [14.0, 15.0, 16.0, 17.0]
- * // [18.0, 19.0, 20.0, 21.0]
- * // [22.0, 23.0, 24.0, 25.0]
- *
- * var a = Cesium.Matrix4.transpose(m, new Cesium.Matrix4());
- *
- * // m remains the same
- * // a = [10.0, 14.0, 18.0, 22.0]
- * // [11.0, 15.0, 19.0, 23.0]
- * // [12.0, 16.0, 20.0, 24.0]
- * // [13.0, 17.0, 21.0, 25.0]
- */
- Matrix4.transpose = function (matrix, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- var matrix1 = matrix[1];
- var matrix2 = matrix[2];
- var matrix3 = matrix[3];
- var matrix6 = matrix[6];
- var matrix7 = matrix[7];
- var matrix11 = matrix[11];
- result[0] = matrix[0];
- result[1] = matrix[4];
- result[2] = matrix[8];
- result[3] = matrix[12];
- result[4] = matrix1;
- result[5] = matrix[5];
- result[6] = matrix[9];
- result[7] = matrix[13];
- result[8] = matrix2;
- result[9] = matrix6;
- result[10] = matrix[10];
- result[11] = matrix[14];
- result[12] = matrix3;
- result[13] = matrix7;
- result[14] = matrix11;
- result[15] = matrix[15];
- return result;
- };
- /**
- * Computes a matrix, which contains the absolute (unsigned) values of the provided matrix's elements.
- *
- * @param {Matrix4} matrix The matrix with signed elements.
- * @param {Matrix4} result The object onto which to store the result.
- * @returns {Matrix4} The modified result parameter.
- */
- Matrix4.abs = function (matrix, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- result[0] = Math.abs(matrix[0]);
- result[1] = Math.abs(matrix[1]);
- result[2] = Math.abs(matrix[2]);
- result[3] = Math.abs(matrix[3]);
- result[4] = Math.abs(matrix[4]);
- result[5] = Math.abs(matrix[5]);
- result[6] = Math.abs(matrix[6]);
- result[7] = Math.abs(matrix[7]);
- result[8] = Math.abs(matrix[8]);
- result[9] = Math.abs(matrix[9]);
- result[10] = Math.abs(matrix[10]);
- result[11] = Math.abs(matrix[11]);
- result[12] = Math.abs(matrix[12]);
- result[13] = Math.abs(matrix[13]);
- result[14] = Math.abs(matrix[14]);
- result[15] = Math.abs(matrix[15]);
- return result;
- };
- /**
- * Compares the provided matrices componentwise and returns
- * <code>true</code> if they are equal, <code>false</code> otherwise.
- *
- * @param {Matrix4} [left] The first matrix.
- * @param {Matrix4} [right] The second matrix.
- * @returns {Boolean} <code>true</code> if left and right are equal, <code>false</code> otherwise.
- *
- * @example
- * //compares two Matrix4 instances
- *
- * // a = [10.0, 14.0, 18.0, 22.0]
- * // [11.0, 15.0, 19.0, 23.0]
- * // [12.0, 16.0, 20.0, 24.0]
- * // [13.0, 17.0, 21.0, 25.0]
- *
- * // b = [10.0, 14.0, 18.0, 22.0]
- * // [11.0, 15.0, 19.0, 23.0]
- * // [12.0, 16.0, 20.0, 24.0]
- * // [13.0, 17.0, 21.0, 25.0]
- *
- * if(Cesium.Matrix4.equals(a,b)) {
- * console.log("Both matrices are equal");
- * } else {
- * console.log("They are not equal");
- * }
- *
- * //Prints "Both matrices are equal" on the console
- */
- Matrix4.equals = function (left, right) {
- // Given that most matrices will be transformation matrices, the elements
- // are tested in order such that the test is likely to fail as early
- // as possible. I _think_ this is just as friendly to the L1 cache
- // as testing in index order. It is certainty faster in practice.
- return (
- left === right ||
- (when.defined(left) &&
- when.defined(right) &&
- // Translation
- left[12] === right[12] &&
- left[13] === right[13] &&
- left[14] === right[14] &&
- // Rotation/scale
- left[0] === right[0] &&
- left[1] === right[1] &&
- left[2] === right[2] &&
- left[4] === right[4] &&
- left[5] === right[5] &&
- left[6] === right[6] &&
- left[8] === right[8] &&
- left[9] === right[9] &&
- left[10] === right[10] &&
- // Bottom row
- left[3] === right[3] &&
- left[7] === right[7] &&
- left[11] === right[11] &&
- left[15] === right[15])
- );
- };
- /**
- * Compares the provided matrices componentwise and returns
- * <code>true</code> if they are within the provided epsilon,
- * <code>false</code> otherwise.
- *
- * @param {Matrix4} [left] The first matrix.
- * @param {Matrix4} [right] The second matrix.
- * @param {Number} [epsilon=0] The epsilon to use for equality testing.
- * @returns {Boolean} <code>true</code> if left and right are within the provided epsilon, <code>false</code> otherwise.
- *
- * @example
- * //compares two Matrix4 instances
- *
- * // a = [10.5, 14.5, 18.5, 22.5]
- * // [11.5, 15.5, 19.5, 23.5]
- * // [12.5, 16.5, 20.5, 24.5]
- * // [13.5, 17.5, 21.5, 25.5]
- *
- * // b = [10.0, 14.0, 18.0, 22.0]
- * // [11.0, 15.0, 19.0, 23.0]
- * // [12.0, 16.0, 20.0, 24.0]
- * // [13.0, 17.0, 21.0, 25.0]
- *
- * if(Cesium.Matrix4.equalsEpsilon(a,b,0.1)){
- * console.log("Difference between both the matrices is less than 0.1");
- * } else {
- * console.log("Difference between both the matrices is not less than 0.1");
- * }
- *
- * //Prints "Difference between both the matrices is not less than 0.1" on the console
- */
- Matrix4.equalsEpsilon = function (left, right, epsilon) {
- epsilon = when.defaultValue(epsilon, 0);
- return (
- left === right ||
- (when.defined(left) &&
- when.defined(right) &&
- Math.abs(left[0] - right[0]) <= epsilon &&
- Math.abs(left[1] - right[1]) <= epsilon &&
- Math.abs(left[2] - right[2]) <= epsilon &&
- Math.abs(left[3] - right[3]) <= epsilon &&
- Math.abs(left[4] - right[4]) <= epsilon &&
- Math.abs(left[5] - right[5]) <= epsilon &&
- Math.abs(left[6] - right[6]) <= epsilon &&
- Math.abs(left[7] - right[7]) <= epsilon &&
- Math.abs(left[8] - right[8]) <= epsilon &&
- Math.abs(left[9] - right[9]) <= epsilon &&
- Math.abs(left[10] - right[10]) <= epsilon &&
- Math.abs(left[11] - right[11]) <= epsilon &&
- Math.abs(left[12] - right[12]) <= epsilon &&
- Math.abs(left[13] - right[13]) <= epsilon &&
- Math.abs(left[14] - right[14]) <= epsilon &&
- Math.abs(left[15] - right[15]) <= epsilon)
- );
- };
- /**
- * Gets the translation portion of the provided matrix, assuming the matrix is a affine transformation matrix.
- *
- * @param {Matrix4} matrix The matrix to use.
- * @param {Cartesian3} result The object onto which to store the result.
- * @returns {Cartesian3} The modified result parameter.
- */
- Matrix4.getTranslation = function (matrix, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- result.x = matrix[12];
- result.y = matrix[13];
- result.z = matrix[14];
- return result;
- };
- /**
- * Gets the upper left 3x3 rotation matrix of the provided matrix, assuming the matrix is an affine transformation matrix.
- *
- * @param {Matrix4} matrix The matrix to use.
- * @param {Matrix3} result The object onto which to store the result.
- * @returns {Matrix3} The modified result parameter.
- *
- * @example
- * // returns a Matrix3 instance from a Matrix4 instance
- *
- * // m = [10.0, 14.0, 18.0, 22.0]
- * // [11.0, 15.0, 19.0, 23.0]
- * // [12.0, 16.0, 20.0, 24.0]
- * // [13.0, 17.0, 21.0, 25.0]
- *
- * var b = new Cesium.Matrix3();
- * Cesium.Matrix4.getMatrix3(m,b);
- *
- * // b = [10.0, 14.0, 18.0]
- * // [11.0, 15.0, 19.0]
- * // [12.0, 16.0, 20.0]
- */
- Matrix4.getMatrix3 = function (matrix, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- result[0] = matrix[0];
- result[1] = matrix[1];
- result[2] = matrix[2];
- result[3] = matrix[4];
- result[4] = matrix[5];
- result[5] = matrix[6];
- result[6] = matrix[8];
- result[7] = matrix[9];
- result[8] = matrix[10];
- return result;
- };
- var scratchInverseRotation = new Matrix3();
- var scratchMatrix3Zero = new Matrix3();
- var scratchBottomRow = new Cartesian4();
- var scratchExpectedBottomRow = new Cartesian4(0.0, 0.0, 0.0, 1.0);
- /**
- * Computes the inverse of the provided matrix using Cramers Rule.
- * If the determinant is zero, the matrix can not be inverted, and an exception is thrown.
- * If the matrix is an affine transformation matrix, it is more efficient
- * to invert it with {@link Matrix4.inverseTransformation}.
- *
- * @param {Matrix4} matrix The matrix to invert.
- * @param {Matrix4} result The object onto which to store the result.
- * @returns {Matrix4} The modified result parameter.
- *
- * @exception {RuntimeError} matrix is not invertible because its determinate is zero.
- */
- Matrix4.inverse = function (matrix, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- //
- // Ported from:
- // ftp://download.intel.com/design/PentiumIII/sml/24504301.pdf
- //
- var src0 = matrix[0];
- var src1 = matrix[4];
- var src2 = matrix[8];
- var src3 = matrix[12];
- var src4 = matrix[1];
- var src5 = matrix[5];
- var src6 = matrix[9];
- var src7 = matrix[13];
- var src8 = matrix[2];
- var src9 = matrix[6];
- var src10 = matrix[10];
- var src11 = matrix[14];
- var src12 = matrix[3];
- var src13 = matrix[7];
- var src14 = matrix[11];
- var src15 = matrix[15];
- // calculate pairs for first 8 elements (cofactors)
- var tmp0 = src10 * src15;
- var tmp1 = src11 * src14;
- var tmp2 = src9 * src15;
- var tmp3 = src11 * src13;
- var tmp4 = src9 * src14;
- var tmp5 = src10 * src13;
- var tmp6 = src8 * src15;
- var tmp7 = src11 * src12;
- var tmp8 = src8 * src14;
- var tmp9 = src10 * src12;
- var tmp10 = src8 * src13;
- var tmp11 = src9 * src12;
- // calculate first 8 elements (cofactors)
- var dst0 =
- tmp0 * src5 +
- tmp3 * src6 +
- tmp4 * src7 -
- (tmp1 * src5 + tmp2 * src6 + tmp5 * src7);
- var dst1 =
- tmp1 * src4 +
- tmp6 * src6 +
- tmp9 * src7 -
- (tmp0 * src4 + tmp7 * src6 + tmp8 * src7);
- var dst2 =
- tmp2 * src4 +
- tmp7 * src5 +
- tmp10 * src7 -
- (tmp3 * src4 + tmp6 * src5 + tmp11 * src7);
- var dst3 =
- tmp5 * src4 +
- tmp8 * src5 +
- tmp11 * src6 -
- (tmp4 * src4 + tmp9 * src5 + tmp10 * src6);
- var dst4 =
- tmp1 * src1 +
- tmp2 * src2 +
- tmp5 * src3 -
- (tmp0 * src1 + tmp3 * src2 + tmp4 * src3);
- var dst5 =
- tmp0 * src0 +
- tmp7 * src2 +
- tmp8 * src3 -
- (tmp1 * src0 + tmp6 * src2 + tmp9 * src3);
- var dst6 =
- tmp3 * src0 +
- tmp6 * src1 +
- tmp11 * src3 -
- (tmp2 * src0 + tmp7 * src1 + tmp10 * src3);
- var dst7 =
- tmp4 * src0 +
- tmp9 * src1 +
- tmp10 * src2 -
- (tmp5 * src0 + tmp8 * src1 + tmp11 * src2);
- // calculate pairs for second 8 elements (cofactors)
- tmp0 = src2 * src7;
- tmp1 = src3 * src6;
- tmp2 = src1 * src7;
- tmp3 = src3 * src5;
- tmp4 = src1 * src6;
- tmp5 = src2 * src5;
- tmp6 = src0 * src7;
- tmp7 = src3 * src4;
- tmp8 = src0 * src6;
- tmp9 = src2 * src4;
- tmp10 = src0 * src5;
- tmp11 = src1 * src4;
- // calculate second 8 elements (cofactors)
- var dst8 =
- tmp0 * src13 +
- tmp3 * src14 +
- tmp4 * src15 -
- (tmp1 * src13 + tmp2 * src14 + tmp5 * src15);
- var dst9 =
- tmp1 * src12 +
- tmp6 * src14 +
- tmp9 * src15 -
- (tmp0 * src12 + tmp7 * src14 + tmp8 * src15);
- var dst10 =
- tmp2 * src12 +
- tmp7 * src13 +
- tmp10 * src15 -
- (tmp3 * src12 + tmp6 * src13 + tmp11 * src15);
- var dst11 =
- tmp5 * src12 +
- tmp8 * src13 +
- tmp11 * src14 -
- (tmp4 * src12 + tmp9 * src13 + tmp10 * src14);
- var dst12 =
- tmp2 * src10 +
- tmp5 * src11 +
- tmp1 * src9 -
- (tmp4 * src11 + tmp0 * src9 + tmp3 * src10);
- var dst13 =
- tmp8 * src11 +
- tmp0 * src8 +
- tmp7 * src10 -
- (tmp6 * src10 + tmp9 * src11 + tmp1 * src8);
- var dst14 =
- tmp6 * src9 +
- tmp11 * src11 +
- tmp3 * src8 -
- (tmp10 * src11 + tmp2 * src8 + tmp7 * src9);
- var dst15 =
- tmp10 * src10 +
- tmp4 * src8 +
- tmp9 * src9 -
- (tmp8 * src9 + tmp11 * src10 + tmp5 * src8);
- // calculate determinant
- var det = src0 * dst0 + src1 * dst1 + src2 * dst2 + src3 * dst3;
- if (Math.abs(det) < _Math.CesiumMath.EPSILON21) {
- // Special case for a zero scale matrix that can occur, for example,
- // when a model's node has a [0, 0, 0] scale.
- if (
- Matrix3.equalsEpsilon(
- Matrix4.getMatrix3(matrix, scratchInverseRotation),
- scratchMatrix3Zero,
- _Math.CesiumMath.EPSILON7
- ) &&
- Cartesian4.equals(
- Matrix4.getRow(matrix, 3, scratchBottomRow),
- scratchExpectedBottomRow
- )
- ) {
- result[0] = 0.0;
- result[1] = 0.0;
- result[2] = 0.0;
- result[3] = 0.0;
- result[4] = 0.0;
- result[5] = 0.0;
- result[6] = 0.0;
- result[7] = 0.0;
- result[8] = 0.0;
- result[9] = 0.0;
- result[10] = 0.0;
- result[11] = 0.0;
- result[12] = -matrix[12];
- result[13] = -matrix[13];
- result[14] = -matrix[14];
- result[15] = 1.0;
- return result;
- }
- throw new RuntimeError.RuntimeError(
- "matrix is not invertible because its determinate is zero."
- );
- }
- // calculate matrix inverse
- det = 1.0 / det;
- result[0] = dst0 * det;
- result[1] = dst1 * det;
- result[2] = dst2 * det;
- result[3] = dst3 * det;
- result[4] = dst4 * det;
- result[5] = dst5 * det;
- result[6] = dst6 * det;
- result[7] = dst7 * det;
- result[8] = dst8 * det;
- result[9] = dst9 * det;
- result[10] = dst10 * det;
- result[11] = dst11 * det;
- result[12] = dst12 * det;
- result[13] = dst13 * det;
- result[14] = dst14 * det;
- result[15] = dst15 * det;
- return result;
- };
- /**
- * Computes the inverse of the provided matrix assuming it is
- * an affine transformation matrix, where the upper left 3x3 elements
- * are a rotation matrix, and the upper three elements in the fourth
- * column are the translation. The bottom row is assumed to be [0, 0, 0, 1].
- * The matrix is not verified to be in the proper form.
- * This method is faster than computing the inverse for a general 4x4
- * matrix using {@link Matrix4.inverse}.
- *
- * @param {Matrix4} matrix The matrix to invert.
- * @param {Matrix4} result The object onto which to store the result.
- * @returns {Matrix4} The modified result parameter.
- */
- Matrix4.inverseTransformation = function (matrix, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- //This function is an optimized version of the below 4 lines.
- //var rT = Matrix3.transpose(Matrix4.getMatrix3(matrix));
- //var rTN = Matrix3.negate(rT);
- //var rTT = Matrix3.multiplyByVector(rTN, Matrix4.getTranslation(matrix));
- //return Matrix4.fromRotationTranslation(rT, rTT, result);
- var matrix0 = matrix[0];
- var matrix1 = matrix[1];
- var matrix2 = matrix[2];
- var matrix4 = matrix[4];
- var matrix5 = matrix[5];
- var matrix6 = matrix[6];
- var matrix8 = matrix[8];
- var matrix9 = matrix[9];
- var matrix10 = matrix[10];
- var vX = matrix[12];
- var vY = matrix[13];
- var vZ = matrix[14];
- var x = -matrix0 * vX - matrix1 * vY - matrix2 * vZ;
- var y = -matrix4 * vX - matrix5 * vY - matrix6 * vZ;
- var z = -matrix8 * vX - matrix9 * vY - matrix10 * vZ;
- result[0] = matrix0;
- result[1] = matrix4;
- result[2] = matrix8;
- result[3] = 0.0;
- result[4] = matrix1;
- result[5] = matrix5;
- result[6] = matrix9;
- result[7] = 0.0;
- result[8] = matrix2;
- result[9] = matrix6;
- result[10] = matrix10;
- result[11] = 0.0;
- result[12] = x;
- result[13] = y;
- result[14] = z;
- result[15] = 1.0;
- return result;
- };
- /**
- * An immutable Matrix4 instance initialized to the identity matrix.
- *
- * @type {Matrix4}
- * @constant
- */
- Matrix4.IDENTITY = Object.freeze(
- new Matrix4(
- 1.0,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- 1.0,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- 1.0,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- 1.0
- )
- );
- /**
- * An immutable Matrix4 instance initialized to the zero matrix.
- *
- * @type {Matrix4}
- * @constant
- */
- Matrix4.ZERO = Object.freeze(
- new Matrix4(
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- 0.0
- )
- );
- /**
- * The index into Matrix4 for column 0, row 0.
- *
- * @type {Number}
- * @constant
- */
- Matrix4.COLUMN0ROW0 = 0;
- /**
- * The index into Matrix4 for column 0, row 1.
- *
- * @type {Number}
- * @constant
- */
- Matrix4.COLUMN0ROW1 = 1;
- /**
- * The index into Matrix4 for column 0, row 2.
- *
- * @type {Number}
- * @constant
- */
- Matrix4.COLUMN0ROW2 = 2;
- /**
- * The index into Matrix4 for column 0, row 3.
- *
- * @type {Number}
- * @constant
- */
- Matrix4.COLUMN0ROW3 = 3;
- /**
- * The index into Matrix4 for column 1, row 0.
- *
- * @type {Number}
- * @constant
- */
- Matrix4.COLUMN1ROW0 = 4;
- /**
- * The index into Matrix4 for column 1, row 1.
- *
- * @type {Number}
- * @constant
- */
- Matrix4.COLUMN1ROW1 = 5;
- /**
- * The index into Matrix4 for column 1, row 2.
- *
- * @type {Number}
- * @constant
- */
- Matrix4.COLUMN1ROW2 = 6;
- /**
- * The index into Matrix4 for column 1, row 3.
- *
- * @type {Number}
- * @constant
- */
- Matrix4.COLUMN1ROW3 = 7;
- /**
- * The index into Matrix4 for column 2, row 0.
- *
- * @type {Number}
- * @constant
- */
- Matrix4.COLUMN2ROW0 = 8;
- /**
- * The index into Matrix4 for column 2, row 1.
- *
- * @type {Number}
- * @constant
- */
- Matrix4.COLUMN2ROW1 = 9;
- /**
- * The index into Matrix4 for column 2, row 2.
- *
- * @type {Number}
- * @constant
- */
- Matrix4.COLUMN2ROW2 = 10;
- /**
- * The index into Matrix4 for column 2, row 3.
- *
- * @type {Number}
- * @constant
- */
- Matrix4.COLUMN2ROW3 = 11;
- /**
- * The index into Matrix4 for column 3, row 0.
- *
- * @type {Number}
- * @constant
- */
- Matrix4.COLUMN3ROW0 = 12;
- /**
- * The index into Matrix4 for column 3, row 1.
- *
- * @type {Number}
- * @constant
- */
- Matrix4.COLUMN3ROW1 = 13;
- /**
- * The index into Matrix4 for column 3, row 2.
- *
- * @type {Number}
- * @constant
- */
- Matrix4.COLUMN3ROW2 = 14;
- /**
- * The index into Matrix4 for column 3, row 3.
- *
- * @type {Number}
- * @constant
- */
- Matrix4.COLUMN3ROW3 = 15;
- Object.defineProperties(Matrix4.prototype, {
- /**
- * Gets the number of items in the collection.
- * @memberof Matrix4.prototype
- *
- * @type {Number}
- */
- length: {
- get: function () {
- return Matrix4.packedLength;
- },
- },
- });
- /**
- * Duplicates the provided Matrix4 instance.
- *
- * @param {Matrix4} [result] The object onto which to store the result.
- * @returns {Matrix4} The modified result parameter or a new Matrix4 instance if one was not provided.
- */
- Matrix4.prototype.clone = function (result) {
- return Matrix4.clone(this, result);
- };
- /**
- * Compares this matrix to the provided matrix componentwise and returns
- * <code>true</code> if they are equal, <code>false</code> otherwise.
- *
- * @param {Matrix4} [right] The right hand side matrix.
- * @returns {Boolean} <code>true</code> if they are equal, <code>false</code> otherwise.
- */
- Matrix4.prototype.equals = function (right) {
- return Matrix4.equals(this, right);
- };
- /**
- * @private
- */
- Matrix4.equalsArray = function (matrix, array, offset) {
- return (
- matrix[0] === array[offset] &&
- matrix[1] === array[offset + 1] &&
- matrix[2] === array[offset + 2] &&
- matrix[3] === array[offset + 3] &&
- matrix[4] === array[offset + 4] &&
- matrix[5] === array[offset + 5] &&
- matrix[6] === array[offset + 6] &&
- matrix[7] === array[offset + 7] &&
- matrix[8] === array[offset + 8] &&
- matrix[9] === array[offset + 9] &&
- matrix[10] === array[offset + 10] &&
- matrix[11] === array[offset + 11] &&
- matrix[12] === array[offset + 12] &&
- matrix[13] === array[offset + 13] &&
- matrix[14] === array[offset + 14] &&
- matrix[15] === array[offset + 15]
- );
- };
- /**
- * Compares this matrix to the provided matrix componentwise and returns
- * <code>true</code> if they are within the provided epsilon,
- * <code>false</code> otherwise.
- *
- * @param {Matrix4} [right] The right hand side matrix.
- * @param {Number} [epsilon=0] The epsilon to use for equality testing.
- * @returns {Boolean} <code>true</code> if they are within the provided epsilon, <code>false</code> otherwise.
- */
- Matrix4.prototype.equalsEpsilon = function (right, epsilon) {
- return Matrix4.equalsEpsilon(this, right, epsilon);
- };
- /**
- * Computes a string representing this Matrix with each row being
- * on a separate line and in the format '(column0, column1, column2, column3)'.
- *
- * @returns {String} A string representing the provided Matrix with each row being on a separate line and in the format '(column0, column1, column2, column3)'.
- */
- Matrix4.prototype.toString = function () {
- return (
- "(" +
- this[0] +
- ", " +
- this[4] +
- ", " +
- this[8] +
- ", " +
- this[12] +
- ")\n" +
- "(" +
- this[1] +
- ", " +
- this[5] +
- ", " +
- this[9] +
- ", " +
- this[13] +
- ")\n" +
- "(" +
- this[2] +
- ", " +
- this[6] +
- ", " +
- this[10] +
- ", " +
- this[14] +
- ")\n" +
- "(" +
- this[3] +
- ", " +
- this[7] +
- ", " +
- this[11] +
- ", " +
- this[15] +
- ")"
- );
- };
- /**
- * A bounding sphere with a center and a radius.
- * @alias BoundingSphere
- * @constructor
- *
- * @param {Cartesian3} [center=Cartesian3.ZERO] The center of the bounding sphere.
- * @param {Number} [radius=0.0] The radius of the bounding sphere.
- *
- * @see AxisAlignedBoundingBox
- * @see BoundingRectangle
- * @see Packable
- */
- function BoundingSphere(center, radius) {
- /**
- * The center point of the sphere.
- * @type {Cartesian3}
- * @default {@link Cartesian3.ZERO}
- */
- this.center = Cartesian2.Cartesian3.clone(when.defaultValue(center, Cartesian2.Cartesian3.ZERO));
- /**
- * The radius of the sphere.
- * @type {Number}
- * @default 0.0
- */
- this.radius = when.defaultValue(radius, 0.0);
- }
- var fromPointsXMin = new Cartesian2.Cartesian3();
- var fromPointsYMin = new Cartesian2.Cartesian3();
- var fromPointsZMin = new Cartesian2.Cartesian3();
- var fromPointsXMax = new Cartesian2.Cartesian3();
- var fromPointsYMax = new Cartesian2.Cartesian3();
- var fromPointsZMax = new Cartesian2.Cartesian3();
- var fromPointsCurrentPos = new Cartesian2.Cartesian3();
- var fromPointsScratch = new Cartesian2.Cartesian3();
- var fromPointsRitterCenter = new Cartesian2.Cartesian3();
- var fromPointsMinBoxPt = new Cartesian2.Cartesian3();
- var fromPointsMaxBoxPt = new Cartesian2.Cartesian3();
- var fromPointsNaiveCenterScratch = new Cartesian2.Cartesian3();
- var volumeConstant = (4.0 / 3.0) * _Math.CesiumMath.PI;
- /**
- * Computes a tight-fitting bounding sphere enclosing a list of 3D Cartesian points.
- * The bounding sphere is computed by running two algorithms, a naive algorithm and
- * Ritter's algorithm. The smaller of the two spheres is used to ensure a tight fit.
- *
- * @param {Cartesian3[]} [positions] An array of points that the bounding sphere will enclose. Each point must have <code>x</code>, <code>y</code>, and <code>z</code> properties.
- * @param {BoundingSphere} [result] The object onto which to store the result.
- * @returns {BoundingSphere} The modified result parameter or a new BoundingSphere instance if one was not provided.
- *
- * @see {@link http://help.agi.com/AGIComponents/html/BlogBoundingSphere.htm|Bounding Sphere computation article}
- */
- BoundingSphere.fromPoints = function (positions, result) {
- if (!when.defined(result)) {
- result = new BoundingSphere();
- }
- if (!when.defined(positions) || positions.length === 0) {
- result.center = Cartesian2.Cartesian3.clone(Cartesian2.Cartesian3.ZERO, result.center);
- result.radius = 0.0;
- return result;
- }
- var currentPos = Cartesian2.Cartesian3.clone(positions[0], fromPointsCurrentPos);
- var xMin = Cartesian2.Cartesian3.clone(currentPos, fromPointsXMin);
- var yMin = Cartesian2.Cartesian3.clone(currentPos, fromPointsYMin);
- var zMin = Cartesian2.Cartesian3.clone(currentPos, fromPointsZMin);
- var xMax = Cartesian2.Cartesian3.clone(currentPos, fromPointsXMax);
- var yMax = Cartesian2.Cartesian3.clone(currentPos, fromPointsYMax);
- var zMax = Cartesian2.Cartesian3.clone(currentPos, fromPointsZMax);
- var numPositions = positions.length;
- var i;
- for (i = 1; i < numPositions; i++) {
- Cartesian2.Cartesian3.clone(positions[i], currentPos);
- var x = currentPos.x;
- var y = currentPos.y;
- var z = currentPos.z;
- // Store points containing the the smallest and largest components
- if (x < xMin.x) {
- Cartesian2.Cartesian3.clone(currentPos, xMin);
- }
- if (x > xMax.x) {
- Cartesian2.Cartesian3.clone(currentPos, xMax);
- }
- if (y < yMin.y) {
- Cartesian2.Cartesian3.clone(currentPos, yMin);
- }
- if (y > yMax.y) {
- Cartesian2.Cartesian3.clone(currentPos, yMax);
- }
- if (z < zMin.z) {
- Cartesian2.Cartesian3.clone(currentPos, zMin);
- }
- if (z > zMax.z) {
- Cartesian2.Cartesian3.clone(currentPos, zMax);
- }
- }
- // Compute x-, y-, and z-spans (Squared distances b/n each component's min. and max.).
- var xSpan = Cartesian2.Cartesian3.magnitudeSquared(
- Cartesian2.Cartesian3.subtract(xMax, xMin, fromPointsScratch)
- );
- var ySpan = Cartesian2.Cartesian3.magnitudeSquared(
- Cartesian2.Cartesian3.subtract(yMax, yMin, fromPointsScratch)
- );
- var zSpan = Cartesian2.Cartesian3.magnitudeSquared(
- Cartesian2.Cartesian3.subtract(zMax, zMin, fromPointsScratch)
- );
- // Set the diameter endpoints to the largest span.
- var diameter1 = xMin;
- var diameter2 = xMax;
- var maxSpan = xSpan;
- if (ySpan > maxSpan) {
- maxSpan = ySpan;
- diameter1 = yMin;
- diameter2 = yMax;
- }
- if (zSpan > maxSpan) {
- maxSpan = zSpan;
- diameter1 = zMin;
- diameter2 = zMax;
- }
- // Calculate the center of the initial sphere found by Ritter's algorithm
- var ritterCenter = fromPointsRitterCenter;
- ritterCenter.x = (diameter1.x + diameter2.x) * 0.5;
- ritterCenter.y = (diameter1.y + diameter2.y) * 0.5;
- ritterCenter.z = (diameter1.z + diameter2.z) * 0.5;
- // Calculate the radius of the initial sphere found by Ritter's algorithm
- var radiusSquared = Cartesian2.Cartesian3.magnitudeSquared(
- Cartesian2.Cartesian3.subtract(diameter2, ritterCenter, fromPointsScratch)
- );
- var ritterRadius = Math.sqrt(radiusSquared);
- // Find the center of the sphere found using the Naive method.
- var minBoxPt = fromPointsMinBoxPt;
- minBoxPt.x = xMin.x;
- minBoxPt.y = yMin.y;
- minBoxPt.z = zMin.z;
- var maxBoxPt = fromPointsMaxBoxPt;
- maxBoxPt.x = xMax.x;
- maxBoxPt.y = yMax.y;
- maxBoxPt.z = zMax.z;
- var naiveCenter = Cartesian2.Cartesian3.midpoint(
- minBoxPt,
- maxBoxPt,
- fromPointsNaiveCenterScratch
- );
- // Begin 2nd pass to find naive radius and modify the ritter sphere.
- var naiveRadius = 0;
- for (i = 0; i < numPositions; i++) {
- Cartesian2.Cartesian3.clone(positions[i], currentPos);
- // Find the furthest point from the naive center to calculate the naive radius.
- var r = Cartesian2.Cartesian3.magnitude(
- Cartesian2.Cartesian3.subtract(currentPos, naiveCenter, fromPointsScratch)
- );
- if (r > naiveRadius) {
- naiveRadius = r;
- }
- // Make adjustments to the Ritter Sphere to include all points.
- var oldCenterToPointSquared = Cartesian2.Cartesian3.magnitudeSquared(
- Cartesian2.Cartesian3.subtract(currentPos, ritterCenter, fromPointsScratch)
- );
- if (oldCenterToPointSquared > radiusSquared) {
- var oldCenterToPoint = Math.sqrt(oldCenterToPointSquared);
- // Calculate new radius to include the point that lies outside
- ritterRadius = (ritterRadius + oldCenterToPoint) * 0.5;
- radiusSquared = ritterRadius * ritterRadius;
- // Calculate center of new Ritter sphere
- var oldToNew = oldCenterToPoint - ritterRadius;
- ritterCenter.x =
- (ritterRadius * ritterCenter.x + oldToNew * currentPos.x) /
- oldCenterToPoint;
- ritterCenter.y =
- (ritterRadius * ritterCenter.y + oldToNew * currentPos.y) /
- oldCenterToPoint;
- ritterCenter.z =
- (ritterRadius * ritterCenter.z + oldToNew * currentPos.z) /
- oldCenterToPoint;
- }
- }
- if (ritterRadius < naiveRadius) {
- Cartesian2.Cartesian3.clone(ritterCenter, result.center);
- result.radius = ritterRadius;
- } else {
- Cartesian2.Cartesian3.clone(naiveCenter, result.center);
- result.radius = naiveRadius;
- }
- return result;
- };
- var defaultProjection = new GeographicProjection();
- var fromRectangle2DLowerLeft = new Cartesian2.Cartesian3();
- var fromRectangle2DUpperRight = new Cartesian2.Cartesian3();
- var fromRectangle2DSouthwest = new Cartesian2.Cartographic();
- var fromRectangle2DNortheast = new Cartesian2.Cartographic();
- /**
- * Computes a bounding sphere from a rectangle projected in 2D.
- *
- * @param {Rectangle} [rectangle] The rectangle around which to create a bounding sphere.
- * @param {Object} [projection=GeographicProjection] The projection used to project the rectangle into 2D.
- * @param {BoundingSphere} [result] The object onto which to store the result.
- * @returns {BoundingSphere} The modified result parameter or a new BoundingSphere instance if none was provided.
- */
- BoundingSphere.fromRectangle2D = function (rectangle, projection, result) {
- return BoundingSphere.fromRectangleWithHeights2D(
- rectangle,
- projection,
- 0.0,
- 0.0,
- result
- );
- };
- /**
- * Computes a bounding sphere from a rectangle projected in 2D. The bounding sphere accounts for the
- * object's minimum and maximum heights over the rectangle.
- *
- * @param {Rectangle} [rectangle] The rectangle around which to create a bounding sphere.
- * @param {Object} [projection=GeographicProjection] The projection used to project the rectangle into 2D.
- * @param {Number} [minimumHeight=0.0] The minimum height over the rectangle.
- * @param {Number} [maximumHeight=0.0] The maximum height over the rectangle.
- * @param {BoundingSphere} [result] The object onto which to store the result.
- * @returns {BoundingSphere} The modified result parameter or a new BoundingSphere instance if none was provided.
- */
- BoundingSphere.fromRectangleWithHeights2D = function (
- rectangle,
- projection,
- minimumHeight,
- maximumHeight,
- result
- ) {
- if (!when.defined(result)) {
- result = new BoundingSphere();
- }
- if (!when.defined(rectangle)) {
- result.center = Cartesian2.Cartesian3.clone(Cartesian2.Cartesian3.ZERO, result.center);
- result.radius = 0.0;
- return result;
- }
- projection = when.defaultValue(projection, defaultProjection);
- Cartesian2.Rectangle.southwest(rectangle, fromRectangle2DSouthwest);
- fromRectangle2DSouthwest.height = minimumHeight;
- Cartesian2.Rectangle.northeast(rectangle, fromRectangle2DNortheast);
- fromRectangle2DNortheast.height = maximumHeight;
- var lowerLeft = projection.project(
- fromRectangle2DSouthwest,
- fromRectangle2DLowerLeft
- );
- var upperRight = projection.project(
- fromRectangle2DNortheast,
- fromRectangle2DUpperRight
- );
- var width = upperRight.x - lowerLeft.x;
- var height = upperRight.y - lowerLeft.y;
- var elevation = upperRight.z - lowerLeft.z;
- result.radius =
- Math.sqrt(width * width + height * height + elevation * elevation) * 0.5;
- var center = result.center;
- center.x = lowerLeft.x + width * 0.5;
- center.y = lowerLeft.y + height * 0.5;
- center.z = lowerLeft.z + elevation * 0.5;
- return result;
- };
- var fromRectangle3DScratch = [];
- /**
- * Computes a bounding sphere from a rectangle in 3D. The bounding sphere is created using a subsample of points
- * on the ellipsoid and contained in the rectangle. It may not be accurate for all rectangles on all types of ellipsoids.
- *
- * @param {Rectangle} [rectangle] The valid rectangle used to create a bounding sphere.
- * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid used to determine positions of the rectangle.
- * @param {Number} [surfaceHeight=0.0] The height above the surface of the ellipsoid.
- * @param {BoundingSphere} [result] The object onto which to store the result.
- * @returns {BoundingSphere} The modified result parameter or a new BoundingSphere instance if none was provided.
- */
- BoundingSphere.fromRectangle3D = function (
- rectangle,
- ellipsoid,
- surfaceHeight,
- result
- ) {
- ellipsoid = when.defaultValue(ellipsoid, Cartesian2.Ellipsoid.WGS84);
- surfaceHeight = when.defaultValue(surfaceHeight, 0.0);
- if (!when.defined(result)) {
- result = new BoundingSphere();
- }
- if (!when.defined(rectangle)) {
- result.center = Cartesian2.Cartesian3.clone(Cartesian2.Cartesian3.ZERO, result.center);
- result.radius = 0.0;
- return result;
- }
- var positions = Cartesian2.Rectangle.subsample(
- rectangle,
- ellipsoid,
- surfaceHeight,
- fromRectangle3DScratch
- );
- return BoundingSphere.fromPoints(positions, result);
- };
- /**
- * Computes a tight-fitting bounding sphere enclosing a list of 3D points, where the points are
- * stored in a flat array in X, Y, Z, order. The bounding sphere is computed by running two
- * algorithms, a naive algorithm and Ritter's algorithm. The smaller of the two spheres is used to
- * ensure a tight fit.
- *
- * @param {Number[]} [positions] An array of points that the bounding sphere will enclose. Each point
- * is formed from three elements in the array in the order X, Y, Z.
- * @param {Cartesian3} [center=Cartesian3.ZERO] The position to which the positions are relative, which need not be the
- * origin of the coordinate system. This is useful when the positions are to be used for
- * relative-to-center (RTC) rendering.
- * @param {Number} [stride=3] The number of array elements per vertex. It must be at least 3, but it may
- * be higher. Regardless of the value of this parameter, the X coordinate of the first position
- * is at array index 0, the Y coordinate is at array index 1, and the Z coordinate is at array index
- * 2. When stride is 3, the X coordinate of the next position then begins at array index 3. If
- * the stride is 5, however, two array elements are skipped and the next position begins at array
- * index 5.
- * @param {BoundingSphere} [result] The object onto which to store the result.
- * @returns {BoundingSphere} The modified result parameter or a new BoundingSphere instance if one was not provided.
- *
- * @example
- * // Compute the bounding sphere from 3 positions, each specified relative to a center.
- * // In addition to the X, Y, and Z coordinates, the points array contains two additional
- * // elements per point which are ignored for the purpose of computing the bounding sphere.
- * var center = new Cesium.Cartesian3(1.0, 2.0, 3.0);
- * var points = [1.0, 2.0, 3.0, 0.1, 0.2,
- * 4.0, 5.0, 6.0, 0.1, 0.2,
- * 7.0, 8.0, 9.0, 0.1, 0.2];
- * var sphere = Cesium.BoundingSphere.fromVertices(points, center, 5);
- *
- * @see {@link http://blogs.agi.com/insight3d/index.php/2008/02/04/a-bounding/|Bounding Sphere computation article}
- */
- BoundingSphere.fromVertices = function (positions, center, stride, result) {
- if (!when.defined(result)) {
- result = new BoundingSphere();
- }
- if (!when.defined(positions) || positions.length === 0) {
- result.center = Cartesian2.Cartesian3.clone(Cartesian2.Cartesian3.ZERO, result.center);
- result.radius = 0.0;
- return result;
- }
- center = when.defaultValue(center, Cartesian2.Cartesian3.ZERO);
- stride = when.defaultValue(stride, 3);
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.number.greaterThanOrEquals("stride", stride, 3);
- //>>includeEnd('debug');
- var currentPos = fromPointsCurrentPos;
- currentPos.x = positions[0] + center.x;
- currentPos.y = positions[1] + center.y;
- currentPos.z = positions[2] + center.z;
- var xMin = Cartesian2.Cartesian3.clone(currentPos, fromPointsXMin);
- var yMin = Cartesian2.Cartesian3.clone(currentPos, fromPointsYMin);
- var zMin = Cartesian2.Cartesian3.clone(currentPos, fromPointsZMin);
- var xMax = Cartesian2.Cartesian3.clone(currentPos, fromPointsXMax);
- var yMax = Cartesian2.Cartesian3.clone(currentPos, fromPointsYMax);
- var zMax = Cartesian2.Cartesian3.clone(currentPos, fromPointsZMax);
- var numElements = positions.length;
- var i;
- for (i = 0; i < numElements; i += stride) {
- var x = positions[i] + center.x;
- var y = positions[i + 1] + center.y;
- var z = positions[i + 2] + center.z;
- currentPos.x = x;
- currentPos.y = y;
- currentPos.z = z;
- // Store points containing the the smallest and largest components
- if (x < xMin.x) {
- Cartesian2.Cartesian3.clone(currentPos, xMin);
- }
- if (x > xMax.x) {
- Cartesian2.Cartesian3.clone(currentPos, xMax);
- }
- if (y < yMin.y) {
- Cartesian2.Cartesian3.clone(currentPos, yMin);
- }
- if (y > yMax.y) {
- Cartesian2.Cartesian3.clone(currentPos, yMax);
- }
- if (z < zMin.z) {
- Cartesian2.Cartesian3.clone(currentPos, zMin);
- }
- if (z > zMax.z) {
- Cartesian2.Cartesian3.clone(currentPos, zMax);
- }
- }
- // Compute x-, y-, and z-spans (Squared distances b/n each component's min. and max.).
- var xSpan = Cartesian2.Cartesian3.magnitudeSquared(
- Cartesian2.Cartesian3.subtract(xMax, xMin, fromPointsScratch)
- );
- var ySpan = Cartesian2.Cartesian3.magnitudeSquared(
- Cartesian2.Cartesian3.subtract(yMax, yMin, fromPointsScratch)
- );
- var zSpan = Cartesian2.Cartesian3.magnitudeSquared(
- Cartesian2.Cartesian3.subtract(zMax, zMin, fromPointsScratch)
- );
- // Set the diameter endpoints to the largest span.
- var diameter1 = xMin;
- var diameter2 = xMax;
- var maxSpan = xSpan;
- if (ySpan > maxSpan) {
- maxSpan = ySpan;
- diameter1 = yMin;
- diameter2 = yMax;
- }
- if (zSpan > maxSpan) {
- maxSpan = zSpan;
- diameter1 = zMin;
- diameter2 = zMax;
- }
- // Calculate the center of the initial sphere found by Ritter's algorithm
- var ritterCenter = fromPointsRitterCenter;
- ritterCenter.x = (diameter1.x + diameter2.x) * 0.5;
- ritterCenter.y = (diameter1.y + diameter2.y) * 0.5;
- ritterCenter.z = (diameter1.z + diameter2.z) * 0.5;
- // Calculate the radius of the initial sphere found by Ritter's algorithm
- var radiusSquared = Cartesian2.Cartesian3.magnitudeSquared(
- Cartesian2.Cartesian3.subtract(diameter2, ritterCenter, fromPointsScratch)
- );
- var ritterRadius = Math.sqrt(radiusSquared);
- // Find the center of the sphere found using the Naive method.
- var minBoxPt = fromPointsMinBoxPt;
- minBoxPt.x = xMin.x;
- minBoxPt.y = yMin.y;
- minBoxPt.z = zMin.z;
- var maxBoxPt = fromPointsMaxBoxPt;
- maxBoxPt.x = xMax.x;
- maxBoxPt.y = yMax.y;
- maxBoxPt.z = zMax.z;
- var naiveCenter = Cartesian2.Cartesian3.midpoint(
- minBoxPt,
- maxBoxPt,
- fromPointsNaiveCenterScratch
- );
- // Begin 2nd pass to find naive radius and modify the ritter sphere.
- var naiveRadius = 0;
- for (i = 0; i < numElements; i += stride) {
- currentPos.x = positions[i] + center.x;
- currentPos.y = positions[i + 1] + center.y;
- currentPos.z = positions[i + 2] + center.z;
- // Find the furthest point from the naive center to calculate the naive radius.
- var r = Cartesian2.Cartesian3.magnitude(
- Cartesian2.Cartesian3.subtract(currentPos, naiveCenter, fromPointsScratch)
- );
- if (r > naiveRadius) {
- naiveRadius = r;
- }
- // Make adjustments to the Ritter Sphere to include all points.
- var oldCenterToPointSquared = Cartesian2.Cartesian3.magnitudeSquared(
- Cartesian2.Cartesian3.subtract(currentPos, ritterCenter, fromPointsScratch)
- );
- if (oldCenterToPointSquared > radiusSquared) {
- var oldCenterToPoint = Math.sqrt(oldCenterToPointSquared);
- // Calculate new radius to include the point that lies outside
- ritterRadius = (ritterRadius + oldCenterToPoint) * 0.5;
- radiusSquared = ritterRadius * ritterRadius;
- // Calculate center of new Ritter sphere
- var oldToNew = oldCenterToPoint - ritterRadius;
- ritterCenter.x =
- (ritterRadius * ritterCenter.x + oldToNew * currentPos.x) /
- oldCenterToPoint;
- ritterCenter.y =
- (ritterRadius * ritterCenter.y + oldToNew * currentPos.y) /
- oldCenterToPoint;
- ritterCenter.z =
- (ritterRadius * ritterCenter.z + oldToNew * currentPos.z) /
- oldCenterToPoint;
- }
- }
- if (ritterRadius < naiveRadius) {
- Cartesian2.Cartesian3.clone(ritterCenter, result.center);
- result.radius = ritterRadius;
- } else {
- Cartesian2.Cartesian3.clone(naiveCenter, result.center);
- result.radius = naiveRadius;
- }
- return result;
- };
- /**
- * Computes a tight-fitting bounding sphere enclosing a list of EncodedCartesian3s, where the points are
- * stored in parallel flat arrays in X, Y, Z, order. The bounding sphere is computed by running two
- * algorithms, a naive algorithm and Ritter's algorithm. The smaller of the two spheres is used to
- * ensure a tight fit.
- *
- * @param {Number[]} [positionsHigh] An array of high bits of the encoded cartesians that the bounding sphere will enclose. Each point
- * is formed from three elements in the array in the order X, Y, Z.
- * @param {Number[]} [positionsLow] An array of low bits of the encoded cartesians that the bounding sphere will enclose. Each point
- * is formed from three elements in the array in the order X, Y, Z.
- * @param {BoundingSphere} [result] The object onto which to store the result.
- * @returns {BoundingSphere} The modified result parameter or a new BoundingSphere instance if one was not provided.
- *
- * @see {@link http://blogs.agi.com/insight3d/index.php/2008/02/04/a-bounding/|Bounding Sphere computation article}
- */
- BoundingSphere.fromEncodedCartesianVertices = function (
- positionsHigh,
- positionsLow,
- result
- ) {
- if (!when.defined(result)) {
- result = new BoundingSphere();
- }
- if (
- !when.defined(positionsHigh) ||
- !when.defined(positionsLow) ||
- positionsHigh.length !== positionsLow.length ||
- positionsHigh.length === 0
- ) {
- result.center = Cartesian2.Cartesian3.clone(Cartesian2.Cartesian3.ZERO, result.center);
- result.radius = 0.0;
- return result;
- }
- var currentPos = fromPointsCurrentPos;
- currentPos.x = positionsHigh[0] + positionsLow[0];
- currentPos.y = positionsHigh[1] + positionsLow[1];
- currentPos.z = positionsHigh[2] + positionsLow[2];
- var xMin = Cartesian2.Cartesian3.clone(currentPos, fromPointsXMin);
- var yMin = Cartesian2.Cartesian3.clone(currentPos, fromPointsYMin);
- var zMin = Cartesian2.Cartesian3.clone(currentPos, fromPointsZMin);
- var xMax = Cartesian2.Cartesian3.clone(currentPos, fromPointsXMax);
- var yMax = Cartesian2.Cartesian3.clone(currentPos, fromPointsYMax);
- var zMax = Cartesian2.Cartesian3.clone(currentPos, fromPointsZMax);
- var numElements = positionsHigh.length;
- var i;
- for (i = 0; i < numElements; i += 3) {
- var x = positionsHigh[i] + positionsLow[i];
- var y = positionsHigh[i + 1] + positionsLow[i + 1];
- var z = positionsHigh[i + 2] + positionsLow[i + 2];
- currentPos.x = x;
- currentPos.y = y;
- currentPos.z = z;
- // Store points containing the the smallest and largest components
- if (x < xMin.x) {
- Cartesian2.Cartesian3.clone(currentPos, xMin);
- }
- if (x > xMax.x) {
- Cartesian2.Cartesian3.clone(currentPos, xMax);
- }
- if (y < yMin.y) {
- Cartesian2.Cartesian3.clone(currentPos, yMin);
- }
- if (y > yMax.y) {
- Cartesian2.Cartesian3.clone(currentPos, yMax);
- }
- if (z < zMin.z) {
- Cartesian2.Cartesian3.clone(currentPos, zMin);
- }
- if (z > zMax.z) {
- Cartesian2.Cartesian3.clone(currentPos, zMax);
- }
- }
- // Compute x-, y-, and z-spans (Squared distances b/n each component's min. and max.).
- var xSpan = Cartesian2.Cartesian3.magnitudeSquared(
- Cartesian2.Cartesian3.subtract(xMax, xMin, fromPointsScratch)
- );
- var ySpan = Cartesian2.Cartesian3.magnitudeSquared(
- Cartesian2.Cartesian3.subtract(yMax, yMin, fromPointsScratch)
- );
- var zSpan = Cartesian2.Cartesian3.magnitudeSquared(
- Cartesian2.Cartesian3.subtract(zMax, zMin, fromPointsScratch)
- );
- // Set the diameter endpoints to the largest span.
- var diameter1 = xMin;
- var diameter2 = xMax;
- var maxSpan = xSpan;
- if (ySpan > maxSpan) {
- maxSpan = ySpan;
- diameter1 = yMin;
- diameter2 = yMax;
- }
- if (zSpan > maxSpan) {
- maxSpan = zSpan;
- diameter1 = zMin;
- diameter2 = zMax;
- }
- // Calculate the center of the initial sphere found by Ritter's algorithm
- var ritterCenter = fromPointsRitterCenter;
- ritterCenter.x = (diameter1.x + diameter2.x) * 0.5;
- ritterCenter.y = (diameter1.y + diameter2.y) * 0.5;
- ritterCenter.z = (diameter1.z + diameter2.z) * 0.5;
- // Calculate the radius of the initial sphere found by Ritter's algorithm
- var radiusSquared = Cartesian2.Cartesian3.magnitudeSquared(
- Cartesian2.Cartesian3.subtract(diameter2, ritterCenter, fromPointsScratch)
- );
- var ritterRadius = Math.sqrt(radiusSquared);
- // Find the center of the sphere found using the Naive method.
- var minBoxPt = fromPointsMinBoxPt;
- minBoxPt.x = xMin.x;
- minBoxPt.y = yMin.y;
- minBoxPt.z = zMin.z;
- var maxBoxPt = fromPointsMaxBoxPt;
- maxBoxPt.x = xMax.x;
- maxBoxPt.y = yMax.y;
- maxBoxPt.z = zMax.z;
- var naiveCenter = Cartesian2.Cartesian3.midpoint(
- minBoxPt,
- maxBoxPt,
- fromPointsNaiveCenterScratch
- );
- // Begin 2nd pass to find naive radius and modify the ritter sphere.
- var naiveRadius = 0;
- for (i = 0; i < numElements; i += 3) {
- currentPos.x = positionsHigh[i] + positionsLow[i];
- currentPos.y = positionsHigh[i + 1] + positionsLow[i + 1];
- currentPos.z = positionsHigh[i + 2] + positionsLow[i + 2];
- // Find the furthest point from the naive center to calculate the naive radius.
- var r = Cartesian2.Cartesian3.magnitude(
- Cartesian2.Cartesian3.subtract(currentPos, naiveCenter, fromPointsScratch)
- );
- if (r > naiveRadius) {
- naiveRadius = r;
- }
- // Make adjustments to the Ritter Sphere to include all points.
- var oldCenterToPointSquared = Cartesian2.Cartesian3.magnitudeSquared(
- Cartesian2.Cartesian3.subtract(currentPos, ritterCenter, fromPointsScratch)
- );
- if (oldCenterToPointSquared > radiusSquared) {
- var oldCenterToPoint = Math.sqrt(oldCenterToPointSquared);
- // Calculate new radius to include the point that lies outside
- ritterRadius = (ritterRadius + oldCenterToPoint) * 0.5;
- radiusSquared = ritterRadius * ritterRadius;
- // Calculate center of new Ritter sphere
- var oldToNew = oldCenterToPoint - ritterRadius;
- ritterCenter.x =
- (ritterRadius * ritterCenter.x + oldToNew * currentPos.x) /
- oldCenterToPoint;
- ritterCenter.y =
- (ritterRadius * ritterCenter.y + oldToNew * currentPos.y) /
- oldCenterToPoint;
- ritterCenter.z =
- (ritterRadius * ritterCenter.z + oldToNew * currentPos.z) /
- oldCenterToPoint;
- }
- }
- if (ritterRadius < naiveRadius) {
- Cartesian2.Cartesian3.clone(ritterCenter, result.center);
- result.radius = ritterRadius;
- } else {
- Cartesian2.Cartesian3.clone(naiveCenter, result.center);
- result.radius = naiveRadius;
- }
- return result;
- };
- /**
- * Computes a bounding sphere from the corner points of an axis-aligned bounding box. The sphere
- * tighly and fully encompases the box.
- *
- * @param {Cartesian3} [corner] The minimum height over the rectangle.
- * @param {Cartesian3} [oppositeCorner] The maximum height over the rectangle.
- * @param {BoundingSphere} [result] The object onto which to store the result.
- * @returns {BoundingSphere} The modified result parameter or a new BoundingSphere instance if none was provided.
- *
- * @example
- * // Create a bounding sphere around the unit cube
- * var sphere = Cesium.BoundingSphere.fromCornerPoints(new Cesium.Cartesian3(-0.5, -0.5, -0.5), new Cesium.Cartesian3(0.5, 0.5, 0.5));
- */
- BoundingSphere.fromCornerPoints = function (corner, oppositeCorner, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("corner", corner);
- Check.Check.typeOf.object("oppositeCorner", oppositeCorner);
- //>>includeEnd('debug');
- if (!when.defined(result)) {
- result = new BoundingSphere();
- }
- var center = Cartesian2.Cartesian3.midpoint(corner, oppositeCorner, result.center);
- result.radius = Cartesian2.Cartesian3.distance(center, oppositeCorner);
- return result;
- };
- /**
- * Creates a bounding sphere encompassing an ellipsoid.
- *
- * @param {Ellipsoid} ellipsoid The ellipsoid around which to create a bounding sphere.
- * @param {BoundingSphere} [result] The object onto which to store the result.
- * @returns {BoundingSphere} The modified result parameter or a new BoundingSphere instance if none was provided.
- *
- * @example
- * var boundingSphere = Cesium.BoundingSphere.fromEllipsoid(ellipsoid);
- */
- BoundingSphere.fromEllipsoid = function (ellipsoid, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("ellipsoid", ellipsoid);
- //>>includeEnd('debug');
- if (!when.defined(result)) {
- result = new BoundingSphere();
- }
- Cartesian2.Cartesian3.clone(Cartesian2.Cartesian3.ZERO, result.center);
- result.radius = ellipsoid.maximumRadius;
- return result;
- };
- var fromBoundingSpheresScratch = new Cartesian2.Cartesian3();
- /**
- * Computes a tight-fitting bounding sphere enclosing the provided array of bounding spheres.
- *
- * @param {BoundingSphere[]} [boundingSpheres] The array of bounding spheres.
- * @param {BoundingSphere} [result] The object onto which to store the result.
- * @returns {BoundingSphere} The modified result parameter or a new BoundingSphere instance if none was provided.
- */
- BoundingSphere.fromBoundingSpheres = function (boundingSpheres, result) {
- if (!when.defined(result)) {
- result = new BoundingSphere();
- }
- if (!when.defined(boundingSpheres) || boundingSpheres.length === 0) {
- result.center = Cartesian2.Cartesian3.clone(Cartesian2.Cartesian3.ZERO, result.center);
- result.radius = 0.0;
- return result;
- }
- var length = boundingSpheres.length;
- if (length === 1) {
- return BoundingSphere.clone(boundingSpheres[0], result);
- }
- if (length === 2) {
- return BoundingSphere.union(boundingSpheres[0], boundingSpheres[1], result);
- }
- var positions = [];
- var i;
- for (i = 0; i < length; i++) {
- positions.push(boundingSpheres[i].center);
- }
- result = BoundingSphere.fromPoints(positions, result);
- var center = result.center;
- var radius = result.radius;
- for (i = 0; i < length; i++) {
- var tmp = boundingSpheres[i];
- radius = Math.max(
- radius,
- Cartesian2.Cartesian3.distance(center, tmp.center, fromBoundingSpheresScratch) +
- tmp.radius
- );
- }
- result.radius = radius;
- return result;
- };
- var fromOrientedBoundingBoxScratchU = new Cartesian2.Cartesian3();
- var fromOrientedBoundingBoxScratchV = new Cartesian2.Cartesian3();
- var fromOrientedBoundingBoxScratchW = new Cartesian2.Cartesian3();
- /**
- * Computes a tight-fitting bounding sphere enclosing the provided oriented bounding box.
- *
- * @param {OrientedBoundingBox} orientedBoundingBox The oriented bounding box.
- * @param {BoundingSphere} [result] The object onto which to store the result.
- * @returns {BoundingSphere} The modified result parameter or a new BoundingSphere instance if none was provided.
- */
- BoundingSphere.fromOrientedBoundingBox = function (
- orientedBoundingBox,
- result
- ) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.defined("orientedBoundingBox", orientedBoundingBox);
- //>>includeEnd('debug');
- if (!when.defined(result)) {
- result = new BoundingSphere();
- }
- var halfAxes = orientedBoundingBox.halfAxes;
- var u = Matrix3.getColumn(halfAxes, 0, fromOrientedBoundingBoxScratchU);
- var v = Matrix3.getColumn(halfAxes, 1, fromOrientedBoundingBoxScratchV);
- var w = Matrix3.getColumn(halfAxes, 2, fromOrientedBoundingBoxScratchW);
- Cartesian2.Cartesian3.add(u, v, u);
- Cartesian2.Cartesian3.add(u, w, u);
- result.center = Cartesian2.Cartesian3.clone(orientedBoundingBox.center, result.center);
- result.radius = Cartesian2.Cartesian3.magnitude(u);
- return result;
- };
- /**
- * Duplicates a BoundingSphere instance.
- *
- * @param {BoundingSphere} sphere The bounding sphere to duplicate.
- * @param {BoundingSphere} [result] The object onto which to store the result.
- * @returns {BoundingSphere} The modified result parameter or a new BoundingSphere instance if none was provided. (Returns undefined if sphere is undefined)
- */
- BoundingSphere.clone = function (sphere, result) {
- if (!when.defined(sphere)) {
- return undefined;
- }
- if (!when.defined(result)) {
- return new BoundingSphere(sphere.center, sphere.radius);
- }
- result.center = Cartesian2.Cartesian3.clone(sphere.center, result.center);
- result.radius = sphere.radius;
- return result;
- };
- /**
- * The number of elements used to pack the object into an array.
- * @type {Number}
- */
- BoundingSphere.packedLength = 4;
- /**
- * Stores the provided instance into the provided array.
- *
- * @param {BoundingSphere} value The value to pack.
- * @param {Number[]} array The array to pack into.
- * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.
- *
- * @returns {Number[]} The array that was packed into
- */
- BoundingSphere.pack = function (value, array, startingIndex) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("value", value);
- Check.Check.defined("array", array);
- //>>includeEnd('debug');
- startingIndex = when.defaultValue(startingIndex, 0);
- var center = value.center;
- array[startingIndex++] = center.x;
- array[startingIndex++] = center.y;
- array[startingIndex++] = center.z;
- array[startingIndex] = value.radius;
- return array;
- };
- /**
- * Retrieves an instance from a packed array.
- *
- * @param {Number[]} array The packed array.
- * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.
- * @param {BoundingSphere} [result] The object into which to store the result.
- * @returns {BoundingSphere} The modified result parameter or a new BoundingSphere instance if one was not provided.
- */
- BoundingSphere.unpack = function (array, startingIndex, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.defined("array", array);
- //>>includeEnd('debug');
- startingIndex = when.defaultValue(startingIndex, 0);
- if (!when.defined(result)) {
- result = new BoundingSphere();
- }
- var center = result.center;
- center.x = array[startingIndex++];
- center.y = array[startingIndex++];
- center.z = array[startingIndex++];
- result.radius = array[startingIndex];
- return result;
- };
- var unionScratch = new Cartesian2.Cartesian3();
- var unionScratchCenter = new Cartesian2.Cartesian3();
- /**
- * Computes a bounding sphere that contains both the left and right bounding spheres.
- *
- * @param {BoundingSphere} left A sphere to enclose in a bounding sphere.
- * @param {BoundingSphere} right A sphere to enclose in a bounding sphere.
- * @param {BoundingSphere} [result] The object onto which to store the result.
- * @returns {BoundingSphere} The modified result parameter or a new BoundingSphere instance if none was provided.
- */
- BoundingSphere.union = function (left, right, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("left", left);
- Check.Check.typeOf.object("right", right);
- //>>includeEnd('debug');
- if (!when.defined(result)) {
- result = new BoundingSphere();
- }
- var leftCenter = left.center;
- var leftRadius = left.radius;
- var rightCenter = right.center;
- var rightRadius = right.radius;
- var toRightCenter = Cartesian2.Cartesian3.subtract(
- rightCenter,
- leftCenter,
- unionScratch
- );
- var centerSeparation = Cartesian2.Cartesian3.magnitude(toRightCenter);
- if (leftRadius >= centerSeparation + rightRadius) {
- // Left sphere wins.
- left.clone(result);
- return result;
- }
- if (rightRadius >= centerSeparation + leftRadius) {
- // Right sphere wins.
- right.clone(result);
- return result;
- }
- // There are two tangent points, one on far side of each sphere.
- var halfDistanceBetweenTangentPoints =
- (leftRadius + centerSeparation + rightRadius) * 0.5;
- // Compute the center point halfway between the two tangent points.
- var center = Cartesian2.Cartesian3.multiplyByScalar(
- toRightCenter,
- (-leftRadius + halfDistanceBetweenTangentPoints) / centerSeparation,
- unionScratchCenter
- );
- Cartesian2.Cartesian3.add(center, leftCenter, center);
- Cartesian2.Cartesian3.clone(center, result.center);
- result.radius = halfDistanceBetweenTangentPoints;
- return result;
- };
- var expandScratch = new Cartesian2.Cartesian3();
- /**
- * Computes a bounding sphere by enlarging the provided sphere to contain the provided point.
- *
- * @param {BoundingSphere} sphere A sphere to expand.
- * @param {Cartesian3} point A point to enclose in a bounding sphere.
- * @param {BoundingSphere} [result] The object onto which to store the result.
- * @returns {BoundingSphere} The modified result parameter or a new BoundingSphere instance if none was provided.
- */
- BoundingSphere.expand = function (sphere, point, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("sphere", sphere);
- Check.Check.typeOf.object("point", point);
- //>>includeEnd('debug');
- result = BoundingSphere.clone(sphere, result);
- var radius = Cartesian2.Cartesian3.magnitude(
- Cartesian2.Cartesian3.subtract(point, result.center, expandScratch)
- );
- if (radius > result.radius) {
- result.radius = radius;
- }
- return result;
- };
- /**
- * Determines which side of a plane a sphere is located.
- *
- * @param {BoundingSphere} sphere The bounding sphere to test.
- * @param {Plane} plane The plane to test against.
- * @returns {Intersect} {@link Intersect.INSIDE} if the entire sphere is on the side of the plane
- * the normal is pointing, {@link Intersect.OUTSIDE} if the entire sphere is
- * on the opposite side, and {@link Intersect.INTERSECTING} if the sphere
- * intersects the plane.
- */
- BoundingSphere.intersectPlane = function (sphere, plane) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("sphere", sphere);
- Check.Check.typeOf.object("plane", plane);
- //>>includeEnd('debug');
- var center = sphere.center;
- var radius = sphere.radius;
- var normal = plane.normal;
- var distanceToPlane = Cartesian2.Cartesian3.dot(normal, center) + plane.distance;
- if (distanceToPlane < -radius) {
- // The center point is negative side of the plane normal
- return Intersect$1.OUTSIDE;
- } else if (distanceToPlane < radius) {
- // The center point is positive side of the plane, but radius extends beyond it; partial overlap
- return Intersect$1.INTERSECTING;
- }
- return Intersect$1.INSIDE;
- };
- /**
- * Applies a 4x4 affine transformation matrix to a bounding sphere.
- *
- * @param {BoundingSphere} sphere The bounding sphere to apply the transformation to.
- * @param {Matrix4} transform The transformation matrix to apply to the bounding sphere.
- * @param {BoundingSphere} [result] The object onto which to store the result.
- * @returns {BoundingSphere} The modified result parameter or a new BoundingSphere instance if none was provided.
- */
- BoundingSphere.transform = function (sphere, transform, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("sphere", sphere);
- Check.Check.typeOf.object("transform", transform);
- //>>includeEnd('debug');
- if (!when.defined(result)) {
- result = new BoundingSphere();
- }
- result.center = Matrix4.multiplyByPoint(
- transform,
- sphere.center,
- result.center
- );
- result.radius = Matrix4.getMaximumScale(transform) * sphere.radius;
- return result;
- };
- var distanceSquaredToScratch = new Cartesian2.Cartesian3();
- /**
- * Computes the estimated distance squared from the closest point on a bounding sphere to a point.
- *
- * @param {BoundingSphere} sphere The sphere.
- * @param {Cartesian3} cartesian The point
- * @returns {Number} The estimated distance squared from the bounding sphere to the point.
- *
- * @example
- * // Sort bounding spheres from back to front
- * spheres.sort(function(a, b) {
- * return Cesium.BoundingSphere.distanceSquaredTo(b, camera.positionWC) - Cesium.BoundingSphere.distanceSquaredTo(a, camera.positionWC);
- * });
- */
- BoundingSphere.distanceSquaredTo = function (sphere, cartesian) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("sphere", sphere);
- Check.Check.typeOf.object("cartesian", cartesian);
- //>>includeEnd('debug');
- var diff = Cartesian2.Cartesian3.subtract(
- sphere.center,
- cartesian,
- distanceSquaredToScratch
- );
- return Cartesian2.Cartesian3.magnitudeSquared(diff) - sphere.radius * sphere.radius;
- };
- /**
- * Applies a 4x4 affine transformation matrix to a bounding sphere where there is no scale
- * The transformation matrix is not verified to have a uniform scale of 1.
- * This method is faster than computing the general bounding sphere transform using {@link BoundingSphere.transform}.
- *
- * @param {BoundingSphere} sphere The bounding sphere to apply the transformation to.
- * @param {Matrix4} transform The transformation matrix to apply to the bounding sphere.
- * @param {BoundingSphere} [result] The object onto which to store the result.
- * @returns {BoundingSphere} The modified result parameter or a new BoundingSphere instance if none was provided.
- *
- * @example
- * var modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(positionOnEllipsoid);
- * var boundingSphere = new Cesium.BoundingSphere();
- * var newBoundingSphere = Cesium.BoundingSphere.transformWithoutScale(boundingSphere, modelMatrix);
- */
- BoundingSphere.transformWithoutScale = function (sphere, transform, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("sphere", sphere);
- Check.Check.typeOf.object("transform", transform);
- //>>includeEnd('debug');
- if (!when.defined(result)) {
- result = new BoundingSphere();
- }
- result.center = Matrix4.multiplyByPoint(
- transform,
- sphere.center,
- result.center
- );
- result.radius = sphere.radius;
- return result;
- };
- var scratchCartesian3 = new Cartesian2.Cartesian3();
- /**
- * The distances calculated by the vector from the center of the bounding sphere to position projected onto direction
- * plus/minus the radius of the bounding sphere.
- * <br>
- * If you imagine the infinite number of planes with normal direction, this computes the smallest distance to the
- * closest and farthest planes from position that intersect the bounding sphere.
- *
- * @param {BoundingSphere} sphere The bounding sphere to calculate the distance to.
- * @param {Cartesian3} position The position to calculate the distance from.
- * @param {Cartesian3} direction The direction from position.
- * @param {Interval} [result] A Interval to store the nearest and farthest distances.
- * @returns {Interval} The nearest and farthest distances on the bounding sphere from position in direction.
- */
- BoundingSphere.computePlaneDistances = function (
- sphere,
- position,
- direction,
- result
- ) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("sphere", sphere);
- Check.Check.typeOf.object("position", position);
- Check.Check.typeOf.object("direction", direction);
- //>>includeEnd('debug');
- if (!when.defined(result)) {
- result = new Interval();
- }
- var toCenter = Cartesian2.Cartesian3.subtract(
- sphere.center,
- position,
- scratchCartesian3
- );
- var mag = Cartesian2.Cartesian3.dot(direction, toCenter);
- result.start = mag - sphere.radius;
- result.stop = mag + sphere.radius;
- return result;
- };
- var projectTo2DNormalScratch = new Cartesian2.Cartesian3();
- var projectTo2DEastScratch = new Cartesian2.Cartesian3();
- var projectTo2DNorthScratch = new Cartesian2.Cartesian3();
- var projectTo2DWestScratch = new Cartesian2.Cartesian3();
- var projectTo2DSouthScratch = new Cartesian2.Cartesian3();
- var projectTo2DCartographicScratch = new Cartesian2.Cartographic();
- var projectTo2DPositionsScratch = new Array(8);
- for (var n = 0; n < 8; ++n) {
- projectTo2DPositionsScratch[n] = new Cartesian2.Cartesian3();
- }
- var projectTo2DProjection = new GeographicProjection();
- /**
- * Creates a bounding sphere in 2D from a bounding sphere in 3D world coordinates.
- *
- * @param {BoundingSphere} sphere The bounding sphere to transform to 2D.
- * @param {Object} [projection=GeographicProjection] The projection to 2D.
- * @param {BoundingSphere} [result] The object onto which to store the result.
- * @returns {BoundingSphere} The modified result parameter or a new BoundingSphere instance if none was provided.
- */
- BoundingSphere.projectTo2D = function (sphere, projection, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("sphere", sphere);
- //>>includeEnd('debug');
- projection = when.defaultValue(projection, projectTo2DProjection);
- var ellipsoid = projection.ellipsoid;
- var center = sphere.center;
- var radius = sphere.radius;
- var normal;
- if (Cartesian2.Cartesian3.equals(center, Cartesian2.Cartesian3.ZERO)) {
- // Bounding sphere is at the center. The geodetic surface normal is not
- // defined here so pick the x-axis as a fallback.
- normal = Cartesian2.Cartesian3.clone(Cartesian2.Cartesian3.UNIT_X, projectTo2DNormalScratch);
- } else {
- normal = ellipsoid.geodeticSurfaceNormal(center, projectTo2DNormalScratch);
- }
- var east = Cartesian2.Cartesian3.cross(
- Cartesian2.Cartesian3.UNIT_Z,
- normal,
- projectTo2DEastScratch
- );
- Cartesian2.Cartesian3.normalize(east, east);
- var north = Cartesian2.Cartesian3.cross(normal, east, projectTo2DNorthScratch);
- Cartesian2.Cartesian3.normalize(north, north);
- Cartesian2.Cartesian3.multiplyByScalar(normal, radius, normal);
- Cartesian2.Cartesian3.multiplyByScalar(north, radius, north);
- Cartesian2.Cartesian3.multiplyByScalar(east, radius, east);
- var south = Cartesian2.Cartesian3.negate(north, projectTo2DSouthScratch);
- var west = Cartesian2.Cartesian3.negate(east, projectTo2DWestScratch);
- var positions = projectTo2DPositionsScratch;
- // top NE corner
- var corner = positions[0];
- Cartesian2.Cartesian3.add(normal, north, corner);
- Cartesian2.Cartesian3.add(corner, east, corner);
- // top NW corner
- corner = positions[1];
- Cartesian2.Cartesian3.add(normal, north, corner);
- Cartesian2.Cartesian3.add(corner, west, corner);
- // top SW corner
- corner = positions[2];
- Cartesian2.Cartesian3.add(normal, south, corner);
- Cartesian2.Cartesian3.add(corner, west, corner);
- // top SE corner
- corner = positions[3];
- Cartesian2.Cartesian3.add(normal, south, corner);
- Cartesian2.Cartesian3.add(corner, east, corner);
- Cartesian2.Cartesian3.negate(normal, normal);
- // bottom NE corner
- corner = positions[4];
- Cartesian2.Cartesian3.add(normal, north, corner);
- Cartesian2.Cartesian3.add(corner, east, corner);
- // bottom NW corner
- corner = positions[5];
- Cartesian2.Cartesian3.add(normal, north, corner);
- Cartesian2.Cartesian3.add(corner, west, corner);
- // bottom SW corner
- corner = positions[6];
- Cartesian2.Cartesian3.add(normal, south, corner);
- Cartesian2.Cartesian3.add(corner, west, corner);
- // bottom SE corner
- corner = positions[7];
- Cartesian2.Cartesian3.add(normal, south, corner);
- Cartesian2.Cartesian3.add(corner, east, corner);
- var length = positions.length;
- for (var i = 0; i < length; ++i) {
- var position = positions[i];
- Cartesian2.Cartesian3.add(center, position, position);
- var cartographic = ellipsoid.cartesianToCartographic(
- position,
- projectTo2DCartographicScratch
- );
- projection.project(cartographic, position);
- }
- result = BoundingSphere.fromPoints(positions, result);
- // swizzle center components
- center = result.center;
- var x = center.x;
- var y = center.y;
- var z = center.z;
- center.x = z;
- center.y = x;
- center.z = y;
- return result;
- };
- /**
- * Determines whether or not a sphere is hidden from view by the occluder.
- *
- * @param {BoundingSphere} sphere The bounding sphere surrounding the occludee object.
- * @param {Occluder} occluder The occluder.
- * @returns {Boolean} <code>true</code> if the sphere is not visible; otherwise <code>false</code>.
- */
- BoundingSphere.isOccluded = function (sphere, occluder) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("sphere", sphere);
- Check.Check.typeOf.object("occluder", occluder);
- //>>includeEnd('debug');
- return !occluder.isBoundingSphereVisible(sphere);
- };
- /**
- * Compares the provided BoundingSphere componentwise and returns
- * <code>true</code> if they are equal, <code>false</code> otherwise.
- *
- * @param {BoundingSphere} [left] The first BoundingSphere.
- * @param {BoundingSphere} [right] The second BoundingSphere.
- * @returns {Boolean} <code>true</code> if left and right are equal, <code>false</code> otherwise.
- */
- BoundingSphere.equals = function (left, right) {
- return (
- left === right ||
- (when.defined(left) &&
- when.defined(right) &&
- Cartesian2.Cartesian3.equals(left.center, right.center) &&
- left.radius === right.radius)
- );
- };
- /**
- * Determines which side of a plane the sphere is located.
- *
- * @param {Plane} plane The plane to test against.
- * @returns {Intersect} {@link Intersect.INSIDE} if the entire sphere is on the side of the plane
- * the normal is pointing, {@link Intersect.OUTSIDE} if the entire sphere is
- * on the opposite side, and {@link Intersect.INTERSECTING} if the sphere
- * intersects the plane.
- */
- BoundingSphere.prototype.intersectPlane = function (plane) {
- return BoundingSphere.intersectPlane(this, plane);
- };
- /**
- * Computes the estimated distance squared from the closest point on a bounding sphere to a point.
- *
- * @param {Cartesian3} cartesian The point
- * @returns {Number} The estimated distance squared from the bounding sphere to the point.
- *
- * @example
- * // Sort bounding spheres from back to front
- * spheres.sort(function(a, b) {
- * return b.distanceSquaredTo(camera.positionWC) - a.distanceSquaredTo(camera.positionWC);
- * });
- */
- BoundingSphere.prototype.distanceSquaredTo = function (cartesian) {
- return BoundingSphere.distanceSquaredTo(this, cartesian);
- };
- /**
- * The distances calculated by the vector from the center of the bounding sphere to position projected onto direction
- * plus/minus the radius of the bounding sphere.
- * <br>
- * If you imagine the infinite number of planes with normal direction, this computes the smallest distance to the
- * closest and farthest planes from position that intersect the bounding sphere.
- *
- * @param {Cartesian3} position The position to calculate the distance from.
- * @param {Cartesian3} direction The direction from position.
- * @param {Interval} [result] A Interval to store the nearest and farthest distances.
- * @returns {Interval} The nearest and farthest distances on the bounding sphere from position in direction.
- */
- BoundingSphere.prototype.computePlaneDistances = function (
- position,
- direction,
- result
- ) {
- return BoundingSphere.computePlaneDistances(
- this,
- position,
- direction,
- result
- );
- };
- /**
- * Determines whether or not a sphere is hidden from view by the occluder.
- *
- * @param {Occluder} occluder The occluder.
- * @returns {Boolean} <code>true</code> if the sphere is not visible; otherwise <code>false</code>.
- */
- BoundingSphere.prototype.isOccluded = function (occluder) {
- return BoundingSphere.isOccluded(this, occluder);
- };
- /**
- * Compares this BoundingSphere against the provided BoundingSphere componentwise and returns
- * <code>true</code> if they are equal, <code>false</code> otherwise.
- *
- * @param {BoundingSphere} [right] The right hand side BoundingSphere.
- * @returns {Boolean} <code>true</code> if they are equal, <code>false</code> otherwise.
- */
- BoundingSphere.prototype.equals = function (right) {
- return BoundingSphere.equals(this, right);
- };
- /**
- * Duplicates this BoundingSphere instance.
- *
- * @param {BoundingSphere} [result] The object onto which to store the result.
- * @returns {BoundingSphere} The modified result parameter or a new BoundingSphere instance if none was provided.
- */
- BoundingSphere.prototype.clone = function (result) {
- return BoundingSphere.clone(this, result);
- };
- /**
- * Computes the radius of the BoundingSphere.
- * @returns {Number} The radius of the BoundingSphere.
- */
- BoundingSphere.prototype.volume = function () {
- var radius = this.radius;
- return volumeConstant * radius * radius * radius;
- };
- var _supportsFullscreen;
- var _names = {
- requestFullscreen: undefined,
- exitFullscreen: undefined,
- fullscreenEnabled: undefined,
- fullscreenElement: undefined,
- fullscreenchange: undefined,
- fullscreenerror: undefined,
- };
- /**
- * Browser-independent functions for working with the standard fullscreen API.
- *
- * @namespace Fullscreen
- *
- * @see {@link http://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html|W3C Fullscreen Living Specification}
- */
- var Fullscreen = {};
- Object.defineProperties(Fullscreen, {
- /**
- * The element that is currently fullscreen, if any. To simply check if the
- * browser is in fullscreen mode or not, use {@link Fullscreen#fullscreen}.
- * @memberof Fullscreen
- * @type {Object}
- * @readonly
- */
- element: {
- get: function () {
- if (!Fullscreen.supportsFullscreen()) {
- return undefined;
- }
- return document[_names.fullscreenElement];
- },
- },
- /**
- * The name of the event on the document that is fired when fullscreen is
- * entered or exited. This event name is intended for use with addEventListener.
- * In your event handler, to determine if the browser is in fullscreen mode or not,
- * use {@link Fullscreen#fullscreen}.
- * @memberof Fullscreen
- * @type {String}
- * @readonly
- */
- changeEventName: {
- get: function () {
- if (!Fullscreen.supportsFullscreen()) {
- return undefined;
- }
- return _names.fullscreenchange;
- },
- },
- /**
- * The name of the event that is fired when a fullscreen error
- * occurs. This event name is intended for use with addEventListener.
- * @memberof Fullscreen
- * @type {String}
- * @readonly
- */
- errorEventName: {
- get: function () {
- if (!Fullscreen.supportsFullscreen()) {
- return undefined;
- }
- return _names.fullscreenerror;
- },
- },
- /**
- * Determine whether the browser will allow an element to be made fullscreen, or not.
- * For example, by default, iframes cannot go fullscreen unless the containing page
- * adds an "allowfullscreen" attribute (or prefixed equivalent).
- * @memberof Fullscreen
- * @type {Boolean}
- * @readonly
- */
- enabled: {
- get: function () {
- if (!Fullscreen.supportsFullscreen()) {
- return undefined;
- }
- return document[_names.fullscreenEnabled];
- },
- },
- /**
- * Determines if the browser is currently in fullscreen mode.
- * @memberof Fullscreen
- * @type {Boolean}
- * @readonly
- */
- fullscreen: {
- get: function () {
- if (!Fullscreen.supportsFullscreen()) {
- return undefined;
- }
- return Fullscreen.element !== null;
- },
- },
- });
- /**
- * Detects whether the browser supports the standard fullscreen API.
- *
- * @returns {Boolean} <code>true</code> if the browser supports the standard fullscreen API,
- * <code>false</code> otherwise.
- */
- Fullscreen.supportsFullscreen = function () {
- if (when.defined(_supportsFullscreen)) {
- return _supportsFullscreen;
- }
- _supportsFullscreen = false;
- var body = document.body;
- if (typeof body.requestFullscreen === "function") {
- // go with the unprefixed, standard set of names
- _names.requestFullscreen = "requestFullscreen";
- _names.exitFullscreen = "exitFullscreen";
- _names.fullscreenEnabled = "fullscreenEnabled";
- _names.fullscreenElement = "fullscreenElement";
- _names.fullscreenchange = "fullscreenchange";
- _names.fullscreenerror = "fullscreenerror";
- _supportsFullscreen = true;
- return _supportsFullscreen;
- }
- //check for the correct combination of prefix plus the various names that browsers use
- var prefixes = ["webkit", "moz", "o", "ms", "khtml"];
- var name;
- for (var i = 0, len = prefixes.length; i < len; ++i) {
- var prefix = prefixes[i];
- // casing of Fullscreen differs across browsers
- name = prefix + "RequestFullscreen";
- if (typeof body[name] === "function") {
- _names.requestFullscreen = name;
- _supportsFullscreen = true;
- } else {
- name = prefix + "RequestFullScreen";
- if (typeof body[name] === "function") {
- _names.requestFullscreen = name;
- _supportsFullscreen = true;
- }
- }
- // disagreement about whether it's "exit" as per spec, or "cancel"
- name = prefix + "ExitFullscreen";
- if (typeof document[name] === "function") {
- _names.exitFullscreen = name;
- } else {
- name = prefix + "CancelFullScreen";
- if (typeof document[name] === "function") {
- _names.exitFullscreen = name;
- }
- }
- // casing of Fullscreen differs across browsers
- name = prefix + "FullscreenEnabled";
- if (document[name] !== undefined) {
- _names.fullscreenEnabled = name;
- } else {
- name = prefix + "FullScreenEnabled";
- if (document[name] !== undefined) {
- _names.fullscreenEnabled = name;
- }
- }
- // casing of Fullscreen differs across browsers
- name = prefix + "FullscreenElement";
- if (document[name] !== undefined) {
- _names.fullscreenElement = name;
- } else {
- name = prefix + "FullScreenElement";
- if (document[name] !== undefined) {
- _names.fullscreenElement = name;
- }
- }
- // thankfully, event names are all lowercase per spec
- name = prefix + "fullscreenchange";
- // event names do not have 'on' in the front, but the property on the document does
- if (document["on" + name] !== undefined) {
- //except on IE
- if (prefix === "ms") {
- name = "MSFullscreenChange";
- }
- _names.fullscreenchange = name;
- }
- name = prefix + "fullscreenerror";
- if (document["on" + name] !== undefined) {
- //except on IE
- if (prefix === "ms") {
- name = "MSFullscreenError";
- }
- _names.fullscreenerror = name;
- }
- }
- return _supportsFullscreen;
- };
- /**
- * Asynchronously requests the browser to enter fullscreen mode on the given element.
- * If fullscreen mode is not supported by the browser, does nothing.
- *
- * @param {Object} element The HTML element which will be placed into fullscreen mode.
- * @param {Object} [vrDevice] The HMDVRDevice device.
- *
- * @example
- * // Put the entire page into fullscreen.
- * Cesium.Fullscreen.requestFullscreen(document.body)
- *
- * // Place only the Cesium canvas into fullscreen.
- * Cesium.Fullscreen.requestFullscreen(scene.canvas)
- */
- Fullscreen.requestFullscreen = function (element, vrDevice) {
- if (!Fullscreen.supportsFullscreen()) {
- return;
- }
- element[_names.requestFullscreen]({ vrDisplay: vrDevice });
- };
- /**
- * Asynchronously exits fullscreen mode. If the browser is not currently
- * in fullscreen, or if fullscreen mode is not supported by the browser, does nothing.
- */
- Fullscreen.exitFullscreen = function () {
- if (!Fullscreen.supportsFullscreen()) {
- return;
- }
- document[_names.exitFullscreen]();
- };
- //For unit tests
- Fullscreen._names = _names;
- var theNavigator;
- if (typeof navigator !== "undefined") {
- theNavigator = navigator;
- } else {
- theNavigator = {};
- }
- function extractVersion(versionString) {
- var parts = versionString.split(".");
- for (var i = 0, len = parts.length; i < len; ++i) {
- parts[i] = parseInt(parts[i], 10);
- }
- return parts;
- }
- var isChromeResult;
- var chromeVersionResult;
- function isChrome() {
- if (!when.defined(isChromeResult)) {
- isChromeResult = false;
- // Edge contains Chrome in the user agent too
- if (!isEdge()) {
- var fields = / Chrome\/([\.0-9]+)/.exec(theNavigator.userAgent);
- if (fields !== null) {
- isChromeResult = true;
- chromeVersionResult = extractVersion(fields[1]);
- }
- }
- }
- return isChromeResult;
- }
- function chromeVersion() {
- return isChrome() && chromeVersionResult;
- }
- var isSafariResult;
- var safariVersionResult;
- function isSafari() {
- if (!when.defined(isSafariResult)) {
- isSafariResult = false;
- // Chrome and Edge contain Safari in the user agent too
- if (
- !isChrome() &&
- !isEdge() &&
- / Safari\/[\.0-9]+/.test(theNavigator.userAgent)
- ) {
- var fields = / Version\/([\.0-9]+)/.exec(theNavigator.userAgent);
- if (fields !== null) {
- isSafariResult = true;
- safariVersionResult = extractVersion(fields[1]);
- }
- }
- }
- return isSafariResult;
- }
- function safariVersion() {
- return isSafari() && safariVersionResult;
- }
- var isWebkitResult;
- var webkitVersionResult;
- function isWebkit() {
- if (!when.defined(isWebkitResult)) {
- isWebkitResult = false;
- var fields = / AppleWebKit\/([\.0-9]+)(\+?)/.exec(theNavigator.userAgent);
- if (fields !== null) {
- isWebkitResult = true;
- webkitVersionResult = extractVersion(fields[1]);
- webkitVersionResult.isNightly = !!fields[2];
- }
- }
- return isWebkitResult;
- }
- function webkitVersion() {
- return isWebkit() && webkitVersionResult;
- }
- var isInternetExplorerResult;
- var internetExplorerVersionResult;
- function isInternetExplorer() {
- if (!when.defined(isInternetExplorerResult)) {
- isInternetExplorerResult = false;
- var fields;
- if (theNavigator.appName === "Microsoft Internet Explorer") {
- fields = /MSIE ([0-9]{1,}[\.0-9]{0,})/.exec(theNavigator.userAgent);
- if (fields !== null) {
- isInternetExplorerResult = true;
- internetExplorerVersionResult = extractVersion(fields[1]);
- }
- } else if (theNavigator.appName === "Netscape") {
- fields = /Trident\/.*rv:([0-9]{1,}[\.0-9]{0,})/.exec(
- theNavigator.userAgent
- );
- if (fields !== null) {
- isInternetExplorerResult = true;
- internetExplorerVersionResult = extractVersion(fields[1]);
- }
- }
- }
- return isInternetExplorerResult;
- }
- function internetExplorerVersion() {
- return isInternetExplorer() && internetExplorerVersionResult;
- }
- var isEdgeResult;
- var edgeVersionResult;
- function isEdge() {
- if (!when.defined(isEdgeResult)) {
- isEdgeResult = false;
- var fields = / Edge\/([\.0-9]+)/.exec(theNavigator.userAgent);
- if (fields !== null) {
- isEdgeResult = true;
- edgeVersionResult = extractVersion(fields[1]);
- }
- }
- return isEdgeResult;
- }
- function edgeVersion() {
- return isEdge() && edgeVersionResult;
- }
- var isFirefoxResult;
- var firefoxVersionResult;
- function isFirefox() {
- if (!when.defined(isFirefoxResult)) {
- isFirefoxResult = false;
- var fields = /Firefox\/([\.0-9]+)/.exec(theNavigator.userAgent);
- if (fields !== null) {
- isFirefoxResult = true;
- firefoxVersionResult = extractVersion(fields[1]);
- }
- }
- return isFirefoxResult;
- }
- var isWindowsResult;
- function isWindows() {
- if (!when.defined(isWindowsResult)) {
- isWindowsResult = /Windows/i.test(theNavigator.appVersion);
- }
- return isWindowsResult;
- }
- function firefoxVersion() {
- return isFirefox() && firefoxVersionResult;
- }
- var hasPointerEvents;
- function supportsPointerEvents() {
- if (!when.defined(hasPointerEvents)) {
- //While navigator.pointerEnabled is deprecated in the W3C specification
- //we still need to use it if it exists in order to support browsers
- //that rely on it, such as the Windows WebBrowser control which defines
- //PointerEvent but sets navigator.pointerEnabled to false.
- //Firefox disabled because of https://github.com/CesiumGS/cesium/issues/6372
- hasPointerEvents =
- !isFirefox() &&
- typeof PointerEvent !== "undefined" &&
- (!when.defined(theNavigator.pointerEnabled) || theNavigator.pointerEnabled);
- }
- return hasPointerEvents;
- }
- var imageRenderingValueResult;
- var supportsImageRenderingPixelatedResult;
- function supportsImageRenderingPixelated() {
- if (!when.defined(supportsImageRenderingPixelatedResult)) {
- var canvas = document.createElement("canvas");
- canvas.setAttribute(
- "style",
- "image-rendering: -moz-crisp-edges;" + "image-rendering: pixelated;"
- );
- //canvas.style.imageRendering will be undefined, null or an empty string on unsupported browsers.
- var tmp = canvas.style.imageRendering;
- supportsImageRenderingPixelatedResult = when.defined(tmp) && tmp !== "";
- if (supportsImageRenderingPixelatedResult) {
- imageRenderingValueResult = tmp;
- }
- }
- return supportsImageRenderingPixelatedResult;
- }
- function imageRenderingValue() {
- return supportsImageRenderingPixelated()
- ? imageRenderingValueResult
- : undefined;
- }
- function supportsWebP() {
- //>>includeStart('debug', pragmas.debug);
- if (!supportsWebP.initialized) {
- throw new Check.DeveloperError(
- "You must call FeatureDetection.supportsWebP.initialize and wait for the promise to resolve before calling FeatureDetection.supportsWebP"
- );
- }
- //>>includeEnd('debug');
- return supportsWebP._result;
- }
- supportsWebP._promise = undefined;
- supportsWebP._result = undefined;
- supportsWebP.initialize = function () {
- // From https://developers.google.com/speed/webp/faq#how_can_i_detect_browser_support_for_webp
- if (when.defined(supportsWebP._promise)) {
- return supportsWebP._promise;
- }
- var supportsWebPDeferred = when.when.defer();
- supportsWebP._promise = supportsWebPDeferred.promise;
- if (isEdge()) {
- // Edge's WebP support with WebGL is incomplete.
- // See bug report: https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/19221241/
- supportsWebP._result = false;
- supportsWebPDeferred.resolve(supportsWebP._result);
- return supportsWebPDeferred.promise;
- }
- var image = new Image();
- image.onload = function () {
- supportsWebP._result = image.width > 0 && image.height > 0;
- supportsWebPDeferred.resolve(supportsWebP._result);
- };
- image.onerror = function () {
- supportsWebP._result = false;
- supportsWebPDeferred.resolve(supportsWebP._result);
- };
- image.src =
- "data:image/webp;base64,UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA";
- return supportsWebPDeferred.promise;
- };
- Object.defineProperties(supportsWebP, {
- initialized: {
- get: function () {
- return when.defined(supportsWebP._result);
- },
- },
- });
- var typedArrayTypes = [];
- if (typeof ArrayBuffer !== "undefined") {
- typedArrayTypes.push(
- Int8Array,
- Uint8Array,
- Int16Array,
- Uint16Array,
- Int32Array,
- Uint32Array,
- Float32Array,
- Float64Array
- );
- if (typeof Uint8ClampedArray !== "undefined") {
- typedArrayTypes.push(Uint8ClampedArray);
- }
- if (typeof Uint8ClampedArray !== "undefined") {
- typedArrayTypes.push(Uint8ClampedArray);
- }
- }
- /**
- * A set of functions to detect whether the current browser supports
- * various features.
- *
- * @namespace FeatureDetection
- */
- var FeatureDetection = {
- isChrome: isChrome,
- chromeVersion: chromeVersion,
- isSafari: isSafari,
- safariVersion: safariVersion,
- isWebkit: isWebkit,
- webkitVersion: webkitVersion,
- isInternetExplorer: isInternetExplorer,
- internetExplorerVersion: internetExplorerVersion,
- isEdge: isEdge,
- edgeVersion: edgeVersion,
- isFirefox: isFirefox,
- firefoxVersion: firefoxVersion,
- isWindows: isWindows,
- hardwareConcurrency: when.defaultValue(theNavigator.hardwareConcurrency, 3),
- supportsPointerEvents: supportsPointerEvents,
- supportsImageRenderingPixelated: supportsImageRenderingPixelated,
- supportsWebP: supportsWebP,
- imageRenderingValue: imageRenderingValue,
- typedArrayTypes: typedArrayTypes,
- };
- /**
- * Detects whether the current browser supports the full screen standard.
- *
- * @returns {Boolean} true if the browser supports the full screen standard, false if not.
- *
- * @see Fullscreen
- * @see {@link http://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html|W3C Fullscreen Living Specification}
- */
- FeatureDetection.supportsFullscreen = function () {
- return Fullscreen.supportsFullscreen();
- };
- /**
- * Detects whether the current browser supports typed arrays.
- *
- * @returns {Boolean} true if the browser supports typed arrays, false if not.
- *
- * @see {@link http://www.khronos.org/registry/typedarray/specs/latest/|Typed Array Specification}
- */
- FeatureDetection.supportsTypedArrays = function () {
- return typeof ArrayBuffer !== "undefined";
- };
- /**
- * Detects whether the current browser supports Web Workers.
- *
- * @returns {Boolean} true if the browsers supports Web Workers, false if not.
- *
- * @see {@link http://www.w3.org/TR/workers/}
- */
- FeatureDetection.supportsWebWorkers = function () {
- return typeof Worker !== "undefined";
- };
- /**
- * Detects whether the current browser supports Web Assembly.
- *
- * @returns {Boolean} true if the browsers supports Web Assembly, false if not.
- *
- * @see {@link https://developer.mozilla.org/en-US/docs/WebAssembly}
- */
- FeatureDetection.supportsWebAssembly = function () {
- return typeof WebAssembly !== "undefined" && !FeatureDetection.isEdge();
- };
- /**
- * A set of 4-dimensional coordinates used to represent rotation in 3-dimensional space.
- * @alias Quaternion
- * @constructor
- *
- * @param {Number} [x=0.0] The X component.
- * @param {Number} [y=0.0] The Y component.
- * @param {Number} [z=0.0] The Z component.
- * @param {Number} [w=0.0] The W component.
- *
- * @see PackableForInterpolation
- */
- function Quaternion(x, y, z, w) {
- /**
- * The X component.
- * @type {Number}
- * @default 0.0
- */
- this.x = when.defaultValue(x, 0.0);
- /**
- * The Y component.
- * @type {Number}
- * @default 0.0
- */
- this.y = when.defaultValue(y, 0.0);
- /**
- * The Z component.
- * @type {Number}
- * @default 0.0
- */
- this.z = when.defaultValue(z, 0.0);
- /**
- * The W component.
- * @type {Number}
- * @default 0.0
- */
- this.w = when.defaultValue(w, 0.0);
- }
- var fromAxisAngleScratch = new Cartesian2.Cartesian3();
- /**
- * Computes a quaternion representing a rotation around an axis.
- *
- * @param {Cartesian3} axis The axis of rotation.
- * @param {Number} angle The angle in radians to rotate around the axis.
- * @param {Quaternion} [result] The object onto which to store the result.
- * @returns {Quaternion} The modified result parameter or a new Quaternion instance if one was not provided.
- */
- Quaternion.fromAxisAngle = function (axis, angle, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("axis", axis);
- Check.Check.typeOf.number("angle", angle);
- //>>includeEnd('debug');
- var halfAngle = angle / 2.0;
- var s = Math.sin(halfAngle);
- fromAxisAngleScratch = Cartesian2.Cartesian3.normalize(axis, fromAxisAngleScratch);
- var x = fromAxisAngleScratch.x * s;
- var y = fromAxisAngleScratch.y * s;
- var z = fromAxisAngleScratch.z * s;
- var w = Math.cos(halfAngle);
- if (!when.defined(result)) {
- return new Quaternion(x, y, z, w);
- }
- result.x = x;
- result.y = y;
- result.z = z;
- result.w = w;
- return result;
- };
- var fromRotationMatrixNext = [1, 2, 0];
- var fromRotationMatrixQuat = new Array(3);
- /**
- * Computes a Quaternion from the provided Matrix3 instance.
- *
- * @param {Matrix3} matrix The rotation matrix.
- * @param {Quaternion} [result] The object onto which to store the result.
- * @returns {Quaternion} The modified result parameter or a new Quaternion instance if one was not provided.
- *
- * @see Matrix3.fromQuaternion
- */
- Quaternion.fromRotationMatrix = function (matrix, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("matrix", matrix);
- //>>includeEnd('debug');
- var root;
- var x;
- var y;
- var z;
- var w;
- var m00 = matrix[Matrix3.COLUMN0ROW0];
- var m11 = matrix[Matrix3.COLUMN1ROW1];
- var m22 = matrix[Matrix3.COLUMN2ROW2];
- var trace = m00 + m11 + m22;
- if (trace > 0.0) {
- // |w| > 1/2, may as well choose w > 1/2
- root = Math.sqrt(trace + 1.0); // 2w
- w = 0.5 * root;
- root = 0.5 / root; // 1/(4w)
- x = (matrix[Matrix3.COLUMN1ROW2] - matrix[Matrix3.COLUMN2ROW1]) * root;
- y = (matrix[Matrix3.COLUMN2ROW0] - matrix[Matrix3.COLUMN0ROW2]) * root;
- z = (matrix[Matrix3.COLUMN0ROW1] - matrix[Matrix3.COLUMN1ROW0]) * root;
- } else {
- // |w| <= 1/2
- var next = fromRotationMatrixNext;
- var i = 0;
- if (m11 > m00) {
- i = 1;
- }
- if (m22 > m00 && m22 > m11) {
- i = 2;
- }
- var j = next[i];
- var k = next[j];
- root = Math.sqrt(
- matrix[Matrix3.getElementIndex(i, i)] -
- matrix[Matrix3.getElementIndex(j, j)] -
- matrix[Matrix3.getElementIndex(k, k)] +
- 1.0
- );
- var quat = fromRotationMatrixQuat;
- quat[i] = 0.5 * root;
- root = 0.5 / root;
- w =
- (matrix[Matrix3.getElementIndex(k, j)] -
- matrix[Matrix3.getElementIndex(j, k)]) *
- root;
- quat[j] =
- (matrix[Matrix3.getElementIndex(j, i)] +
- matrix[Matrix3.getElementIndex(i, j)]) *
- root;
- quat[k] =
- (matrix[Matrix3.getElementIndex(k, i)] +
- matrix[Matrix3.getElementIndex(i, k)]) *
- root;
- x = -quat[0];
- y = -quat[1];
- z = -quat[2];
- }
- if (!when.defined(result)) {
- return new Quaternion(x, y, z, w);
- }
- result.x = x;
- result.y = y;
- result.z = z;
- result.w = w;
- return result;
- };
- var scratchHPRQuaternion = new Quaternion();
- var scratchHeadingQuaternion = new Quaternion();
- var scratchPitchQuaternion = new Quaternion();
- var scratchRollQuaternion = new Quaternion();
- /**
- * Computes a rotation from the given heading, pitch and roll angles. Heading is the rotation about the
- * negative z axis. Pitch is the rotation about the negative y axis. Roll is the rotation about
- * the positive x axis.
- *
- * @param {HeadingPitchRoll} headingPitchRoll The rotation expressed as a heading, pitch and roll.
- * @param {Quaternion} [result] The object onto which to store the result.
- * @returns {Quaternion} The modified result parameter or a new Quaternion instance if none was provided.
- */
- Quaternion.fromHeadingPitchRoll = function (headingPitchRoll, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("headingPitchRoll", headingPitchRoll);
- //>>includeEnd('debug');
- scratchRollQuaternion = Quaternion.fromAxisAngle(
- Cartesian2.Cartesian3.UNIT_X,
- headingPitchRoll.roll,
- scratchHPRQuaternion
- );
- scratchPitchQuaternion = Quaternion.fromAxisAngle(
- Cartesian2.Cartesian3.UNIT_Y,
- -headingPitchRoll.pitch,
- result
- );
- result = Quaternion.multiply(
- scratchPitchQuaternion,
- scratchRollQuaternion,
- scratchPitchQuaternion
- );
- scratchHeadingQuaternion = Quaternion.fromAxisAngle(
- Cartesian2.Cartesian3.UNIT_Z,
- -headingPitchRoll.heading,
- scratchHPRQuaternion
- );
- return Quaternion.multiply(scratchHeadingQuaternion, result, result);
- };
- var sampledQuaternionAxis = new Cartesian2.Cartesian3();
- var sampledQuaternionRotation = new Cartesian2.Cartesian3();
- var sampledQuaternionTempQuaternion = new Quaternion();
- var sampledQuaternionQuaternion0 = new Quaternion();
- var sampledQuaternionQuaternion0Conjugate = new Quaternion();
- /**
- * The number of elements used to pack the object into an array.
- * @type {Number}
- */
- Quaternion.packedLength = 4;
- /**
- * Stores the provided instance into the provided array.
- *
- * @param {Quaternion} value The value to pack.
- * @param {Number[]} array The array to pack into.
- * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.
- *
- * @returns {Number[]} The array that was packed into
- */
- Quaternion.pack = function (value, array, startingIndex) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("value", value);
- Check.Check.defined("array", array);
- //>>includeEnd('debug');
- startingIndex = when.defaultValue(startingIndex, 0);
- array[startingIndex++] = value.x;
- array[startingIndex++] = value.y;
- array[startingIndex++] = value.z;
- array[startingIndex] = value.w;
- return array;
- };
- /**
- * Retrieves an instance from a packed array.
- *
- * @param {Number[]} array The packed array.
- * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.
- * @param {Quaternion} [result] The object into which to store the result.
- * @returns {Quaternion} The modified result parameter or a new Quaternion instance if one was not provided.
- */
- Quaternion.unpack = function (array, startingIndex, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.defined("array", array);
- //>>includeEnd('debug');
- startingIndex = when.defaultValue(startingIndex, 0);
- if (!when.defined(result)) {
- result = new Quaternion();
- }
- result.x = array[startingIndex];
- result.y = array[startingIndex + 1];
- result.z = array[startingIndex + 2];
- result.w = array[startingIndex + 3];
- return result;
- };
- /**
- * The number of elements used to store the object into an array in its interpolatable form.
- * @type {Number}
- */
- Quaternion.packedInterpolationLength = 3;
- /**
- * Converts a packed array into a form suitable for interpolation.
- *
- * @param {Number[]} packedArray The packed array.
- * @param {Number} [startingIndex=0] The index of the first element to be converted.
- * @param {Number} [lastIndex=packedArray.length] The index of the last element to be converted.
- * @param {Number[]} [result] The object into which to store the result.
- */
- Quaternion.convertPackedArrayForInterpolation = function (
- packedArray,
- startingIndex,
- lastIndex,
- result
- ) {
- Quaternion.unpack(
- packedArray,
- lastIndex * 4,
- sampledQuaternionQuaternion0Conjugate
- );
- Quaternion.conjugate(
- sampledQuaternionQuaternion0Conjugate,
- sampledQuaternionQuaternion0Conjugate
- );
- for (var i = 0, len = lastIndex - startingIndex + 1; i < len; i++) {
- var offset = i * 3;
- Quaternion.unpack(
- packedArray,
- (startingIndex + i) * 4,
- sampledQuaternionTempQuaternion
- );
- Quaternion.multiply(
- sampledQuaternionTempQuaternion,
- sampledQuaternionQuaternion0Conjugate,
- sampledQuaternionTempQuaternion
- );
- if (sampledQuaternionTempQuaternion.w < 0) {
- Quaternion.negate(
- sampledQuaternionTempQuaternion,
- sampledQuaternionTempQuaternion
- );
- }
- Quaternion.computeAxis(
- sampledQuaternionTempQuaternion,
- sampledQuaternionAxis
- );
- var angle = Quaternion.computeAngle(sampledQuaternionTempQuaternion);
- if (!when.defined(result)) {
- result = [];
- }
- result[offset] = sampledQuaternionAxis.x * angle;
- result[offset + 1] = sampledQuaternionAxis.y * angle;
- result[offset + 2] = sampledQuaternionAxis.z * angle;
- }
- };
- /**
- * Retrieves an instance from a packed array converted with {@link convertPackedArrayForInterpolation}.
- *
- * @param {Number[]} array The array previously packed for interpolation.
- * @param {Number[]} sourceArray The original packed array.
- * @param {Number} [firstIndex=0] The firstIndex used to convert the array.
- * @param {Number} [lastIndex=packedArray.length] The lastIndex used to convert the array.
- * @param {Quaternion} [result] The object into which to store the result.
- * @returns {Quaternion} The modified result parameter or a new Quaternion instance if one was not provided.
- */
- Quaternion.unpackInterpolationResult = function (
- array,
- sourceArray,
- firstIndex,
- lastIndex,
- result
- ) {
- if (!when.defined(result)) {
- result = new Quaternion();
- }
- Cartesian2.Cartesian3.fromArray(array, 0, sampledQuaternionRotation);
- var magnitude = Cartesian2.Cartesian3.magnitude(sampledQuaternionRotation);
- Quaternion.unpack(sourceArray, lastIndex * 4, sampledQuaternionQuaternion0);
- if (magnitude === 0) {
- Quaternion.clone(Quaternion.IDENTITY, sampledQuaternionTempQuaternion);
- } else {
- Quaternion.fromAxisAngle(
- sampledQuaternionRotation,
- magnitude,
- sampledQuaternionTempQuaternion
- );
- }
- return Quaternion.multiply(
- sampledQuaternionTempQuaternion,
- sampledQuaternionQuaternion0,
- result
- );
- };
- /**
- * Duplicates a Quaternion instance.
- *
- * @param {Quaternion} quaternion The quaternion to duplicate.
- * @param {Quaternion} [result] The object onto which to store the result.
- * @returns {Quaternion} The modified result parameter or a new Quaternion instance if one was not provided. (Returns undefined if quaternion is undefined)
- */
- Quaternion.clone = function (quaternion, result) {
- if (!when.defined(quaternion)) {
- return undefined;
- }
- if (!when.defined(result)) {
- return new Quaternion(
- quaternion.x,
- quaternion.y,
- quaternion.z,
- quaternion.w
- );
- }
- result.x = quaternion.x;
- result.y = quaternion.y;
- result.z = quaternion.z;
- result.w = quaternion.w;
- return result;
- };
- /**
- * Computes the conjugate of the provided quaternion.
- *
- * @param {Quaternion} quaternion The quaternion to conjugate.
- * @param {Quaternion} result The object onto which to store the result.
- * @returns {Quaternion} The modified result parameter.
- */
- Quaternion.conjugate = function (quaternion, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("quaternion", quaternion);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- result.x = -quaternion.x;
- result.y = -quaternion.y;
- result.z = -quaternion.z;
- result.w = quaternion.w;
- return result;
- };
- /**
- * Computes magnitude squared for the provided quaternion.
- *
- * @param {Quaternion} quaternion The quaternion to conjugate.
- * @returns {Number} The magnitude squared.
- */
- Quaternion.magnitudeSquared = function (quaternion) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("quaternion", quaternion);
- //>>includeEnd('debug');
- return (
- quaternion.x * quaternion.x +
- quaternion.y * quaternion.y +
- quaternion.z * quaternion.z +
- quaternion.w * quaternion.w
- );
- };
- /**
- * Computes magnitude for the provided quaternion.
- *
- * @param {Quaternion} quaternion The quaternion to conjugate.
- * @returns {Number} The magnitude.
- */
- Quaternion.magnitude = function (quaternion) {
- return Math.sqrt(Quaternion.magnitudeSquared(quaternion));
- };
- /**
- * Computes the normalized form of the provided quaternion.
- *
- * @param {Quaternion} quaternion The quaternion to normalize.
- * @param {Quaternion} result The object onto which to store the result.
- * @returns {Quaternion} The modified result parameter.
- */
- Quaternion.normalize = function (quaternion, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- var inverseMagnitude = 1.0 / Quaternion.magnitude(quaternion);
- var x = quaternion.x * inverseMagnitude;
- var y = quaternion.y * inverseMagnitude;
- var z = quaternion.z * inverseMagnitude;
- var w = quaternion.w * inverseMagnitude;
- result.x = x;
- result.y = y;
- result.z = z;
- result.w = w;
- return result;
- };
- /**
- * Computes the inverse of the provided quaternion.
- *
- * @param {Quaternion} quaternion The quaternion to normalize.
- * @param {Quaternion} result The object onto which to store the result.
- * @returns {Quaternion} The modified result parameter.
- */
- Quaternion.inverse = function (quaternion, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- var magnitudeSquared = Quaternion.magnitudeSquared(quaternion);
- result = Quaternion.conjugate(quaternion, result);
- return Quaternion.multiplyByScalar(result, 1.0 / magnitudeSquared, result);
- };
- /**
- * Computes the componentwise sum of two quaternions.
- *
- * @param {Quaternion} left The first quaternion.
- * @param {Quaternion} right The second quaternion.
- * @param {Quaternion} result The object onto which to store the result.
- * @returns {Quaternion} The modified result parameter.
- */
- Quaternion.add = function (left, right, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("left", left);
- Check.Check.typeOf.object("right", right);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- result.x = left.x + right.x;
- result.y = left.y + right.y;
- result.z = left.z + right.z;
- result.w = left.w + right.w;
- return result;
- };
- /**
- * Computes the componentwise difference of two quaternions.
- *
- * @param {Quaternion} left The first quaternion.
- * @param {Quaternion} right The second quaternion.
- * @param {Quaternion} result The object onto which to store the result.
- * @returns {Quaternion} The modified result parameter.
- */
- Quaternion.subtract = function (left, right, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("left", left);
- Check.Check.typeOf.object("right", right);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- result.x = left.x - right.x;
- result.y = left.y - right.y;
- result.z = left.z - right.z;
- result.w = left.w - right.w;
- return result;
- };
- /**
- * Negates the provided quaternion.
- *
- * @param {Quaternion} quaternion The quaternion to be negated.
- * @param {Quaternion} result The object onto which to store the result.
- * @returns {Quaternion} The modified result parameter.
- */
- Quaternion.negate = function (quaternion, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("quaternion", quaternion);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- result.x = -quaternion.x;
- result.y = -quaternion.y;
- result.z = -quaternion.z;
- result.w = -quaternion.w;
- return result;
- };
- /**
- * Computes the dot (scalar) product of two quaternions.
- *
- * @param {Quaternion} left The first quaternion.
- * @param {Quaternion} right The second quaternion.
- * @returns {Number} The dot product.
- */
- Quaternion.dot = function (left, right) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("left", left);
- Check.Check.typeOf.object("right", right);
- //>>includeEnd('debug');
- return (
- left.x * right.x + left.y * right.y + left.z * right.z + left.w * right.w
- );
- };
- /**
- * Computes the product of two quaternions.
- *
- * @param {Quaternion} left The first quaternion.
- * @param {Quaternion} right The second quaternion.
- * @param {Quaternion} result The object onto which to store the result.
- * @returns {Quaternion} The modified result parameter.
- */
- Quaternion.multiply = function (left, right, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("left", left);
- Check.Check.typeOf.object("right", right);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- var leftX = left.x;
- var leftY = left.y;
- var leftZ = left.z;
- var leftW = left.w;
- var rightX = right.x;
- var rightY = right.y;
- var rightZ = right.z;
- var rightW = right.w;
- var x = leftW * rightX + leftX * rightW + leftY * rightZ - leftZ * rightY;
- var y = leftW * rightY - leftX * rightZ + leftY * rightW + leftZ * rightX;
- var z = leftW * rightZ + leftX * rightY - leftY * rightX + leftZ * rightW;
- var w = leftW * rightW - leftX * rightX - leftY * rightY - leftZ * rightZ;
- result.x = x;
- result.y = y;
- result.z = z;
- result.w = w;
- return result;
- };
- /**
- * Multiplies the provided quaternion componentwise by the provided scalar.
- *
- * @param {Quaternion} quaternion The quaternion to be scaled.
- * @param {Number} scalar The scalar to multiply with.
- * @param {Quaternion} result The object onto which to store the result.
- * @returns {Quaternion} The modified result parameter.
- */
- Quaternion.multiplyByScalar = function (quaternion, scalar, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("quaternion", quaternion);
- Check.Check.typeOf.number("scalar", scalar);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- result.x = quaternion.x * scalar;
- result.y = quaternion.y * scalar;
- result.z = quaternion.z * scalar;
- result.w = quaternion.w * scalar;
- return result;
- };
- /**
- * Divides the provided quaternion componentwise by the provided scalar.
- *
- * @param {Quaternion} quaternion The quaternion to be divided.
- * @param {Number} scalar The scalar to divide by.
- * @param {Quaternion} result The object onto which to store the result.
- * @returns {Quaternion} The modified result parameter.
- */
- Quaternion.divideByScalar = function (quaternion, scalar, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("quaternion", quaternion);
- Check.Check.typeOf.number("scalar", scalar);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- result.x = quaternion.x / scalar;
- result.y = quaternion.y / scalar;
- result.z = quaternion.z / scalar;
- result.w = quaternion.w / scalar;
- return result;
- };
- /**
- * Computes the axis of rotation of the provided quaternion.
- *
- * @param {Quaternion} quaternion The quaternion to use.
- * @param {Cartesian3} result The object onto which to store the result.
- * @returns {Cartesian3} The modified result parameter.
- */
- Quaternion.computeAxis = function (quaternion, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("quaternion", quaternion);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- var w = quaternion.w;
- if (Math.abs(w - 1.0) < _Math.CesiumMath.EPSILON6) {
- result.x = result.y = result.z = 0;
- return result;
- }
- var scalar = 1.0 / Math.sqrt(1.0 - w * w);
- result.x = quaternion.x * scalar;
- result.y = quaternion.y * scalar;
- result.z = quaternion.z * scalar;
- return result;
- };
- /**
- * Computes the angle of rotation of the provided quaternion.
- *
- * @param {Quaternion} quaternion The quaternion to use.
- * @returns {Number} The angle of rotation.
- */
- Quaternion.computeAngle = function (quaternion) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("quaternion", quaternion);
- //>>includeEnd('debug');
- if (Math.abs(quaternion.w - 1.0) < _Math.CesiumMath.EPSILON6) {
- return 0.0;
- }
- return 2.0 * Math.acos(quaternion.w);
- };
- var lerpScratch$1 = new Quaternion();
- /**
- * Computes the linear interpolation or extrapolation at t using the provided quaternions.
- *
- * @param {Quaternion} start The value corresponding to t at 0.0.
- * @param {Quaternion} end The value corresponding to t at 1.0.
- * @param {Number} t The point along t at which to interpolate.
- * @param {Quaternion} result The object onto which to store the result.
- * @returns {Quaternion} The modified result parameter.
- */
- Quaternion.lerp = function (start, end, t, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("start", start);
- Check.Check.typeOf.object("end", end);
- Check.Check.typeOf.number("t", t);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- lerpScratch$1 = Quaternion.multiplyByScalar(end, t, lerpScratch$1);
- result = Quaternion.multiplyByScalar(start, 1.0 - t, result);
- return Quaternion.add(lerpScratch$1, result, result);
- };
- var slerpEndNegated = new Quaternion();
- var slerpScaledP = new Quaternion();
- var slerpScaledR = new Quaternion();
- /**
- * Computes the spherical linear interpolation or extrapolation at t using the provided quaternions.
- *
- * @param {Quaternion} start The value corresponding to t at 0.0.
- * @param {Quaternion} end The value corresponding to t at 1.0.
- * @param {Number} t The point along t at which to interpolate.
- * @param {Quaternion} result The object onto which to store the result.
- * @returns {Quaternion} The modified result parameter.
- *
- * @see Quaternion#fastSlerp
- */
- Quaternion.slerp = function (start, end, t, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("start", start);
- Check.Check.typeOf.object("end", end);
- Check.Check.typeOf.number("t", t);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- var dot = Quaternion.dot(start, end);
- // The angle between start must be acute. Since q and -q represent
- // the same rotation, negate q to get the acute angle.
- var r = end;
- if (dot < 0.0) {
- dot = -dot;
- r = slerpEndNegated = Quaternion.negate(end, slerpEndNegated);
- }
- // dot > 0, as the dot product approaches 1, the angle between the
- // quaternions vanishes. use linear interpolation.
- if (1.0 - dot < _Math.CesiumMath.EPSILON6) {
- return Quaternion.lerp(start, r, t, result);
- }
- var theta = Math.acos(dot);
- slerpScaledP = Quaternion.multiplyByScalar(
- start,
- Math.sin((1 - t) * theta),
- slerpScaledP
- );
- slerpScaledR = Quaternion.multiplyByScalar(
- r,
- Math.sin(t * theta),
- slerpScaledR
- );
- result = Quaternion.add(slerpScaledP, slerpScaledR, result);
- return Quaternion.multiplyByScalar(result, 1.0 / Math.sin(theta), result);
- };
- /**
- * The logarithmic quaternion function.
- *
- * @param {Quaternion} quaternion The unit quaternion.
- * @param {Cartesian3} result The object onto which to store the result.
- * @returns {Cartesian3} The modified result parameter.
- */
- Quaternion.log = function (quaternion, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("quaternion", quaternion);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- var theta = _Math.CesiumMath.acosClamped(quaternion.w);
- var thetaOverSinTheta = 0.0;
- if (theta !== 0.0) {
- thetaOverSinTheta = theta / Math.sin(theta);
- }
- return Cartesian2.Cartesian3.multiplyByScalar(quaternion, thetaOverSinTheta, result);
- };
- /**
- * The exponential quaternion function.
- *
- * @param {Cartesian3} cartesian The cartesian.
- * @param {Quaternion} result The object onto which to store the result.
- * @returns {Quaternion} The modified result parameter.
- */
- Quaternion.exp = function (cartesian, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("cartesian", cartesian);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- var theta = Cartesian2.Cartesian3.magnitude(cartesian);
- var sinThetaOverTheta = 0.0;
- if (theta !== 0.0) {
- sinThetaOverTheta = Math.sin(theta) / theta;
- }
- result.x = cartesian.x * sinThetaOverTheta;
- result.y = cartesian.y * sinThetaOverTheta;
- result.z = cartesian.z * sinThetaOverTheta;
- result.w = Math.cos(theta);
- return result;
- };
- var squadScratchCartesian0 = new Cartesian2.Cartesian3();
- var squadScratchCartesian1 = new Cartesian2.Cartesian3();
- var squadScratchQuaternion0 = new Quaternion();
- var squadScratchQuaternion1 = new Quaternion();
- /**
- * Computes an inner quadrangle point.
- * <p>This will compute quaternions that ensure a squad curve is C<sup>1</sup>.</p>
- *
- * @param {Quaternion} q0 The first quaternion.
- * @param {Quaternion} q1 The second quaternion.
- * @param {Quaternion} q2 The third quaternion.
- * @param {Quaternion} result The object onto which to store the result.
- * @returns {Quaternion} The modified result parameter.
- *
- * @see Quaternion#squad
- */
- Quaternion.computeInnerQuadrangle = function (q0, q1, q2, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("q0", q0);
- Check.Check.typeOf.object("q1", q1);
- Check.Check.typeOf.object("q2", q2);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- var qInv = Quaternion.conjugate(q1, squadScratchQuaternion0);
- Quaternion.multiply(qInv, q2, squadScratchQuaternion1);
- var cart0 = Quaternion.log(squadScratchQuaternion1, squadScratchCartesian0);
- Quaternion.multiply(qInv, q0, squadScratchQuaternion1);
- var cart1 = Quaternion.log(squadScratchQuaternion1, squadScratchCartesian1);
- Cartesian2.Cartesian3.add(cart0, cart1, cart0);
- Cartesian2.Cartesian3.multiplyByScalar(cart0, 0.25, cart0);
- Cartesian2.Cartesian3.negate(cart0, cart0);
- Quaternion.exp(cart0, squadScratchQuaternion0);
- return Quaternion.multiply(q1, squadScratchQuaternion0, result);
- };
- /**
- * Computes the spherical quadrangle interpolation between quaternions.
- *
- * @param {Quaternion} q0 The first quaternion.
- * @param {Quaternion} q1 The second quaternion.
- * @param {Quaternion} s0 The first inner quadrangle.
- * @param {Quaternion} s1 The second inner quadrangle.
- * @param {Number} t The time in [0,1] used to interpolate.
- * @param {Quaternion} result The object onto which to store the result.
- * @returns {Quaternion} The modified result parameter.
- *
- *
- * @example
- * // 1. compute the squad interpolation between two quaternions on a curve
- * var s0 = Cesium.Quaternion.computeInnerQuadrangle(quaternions[i - 1], quaternions[i], quaternions[i + 1], new Cesium.Quaternion());
- * var s1 = Cesium.Quaternion.computeInnerQuadrangle(quaternions[i], quaternions[i + 1], quaternions[i + 2], new Cesium.Quaternion());
- * var q = Cesium.Quaternion.squad(quaternions[i], quaternions[i + 1], s0, s1, t, new Cesium.Quaternion());
- *
- * // 2. compute the squad interpolation as above but where the first quaternion is a end point.
- * var s1 = Cesium.Quaternion.computeInnerQuadrangle(quaternions[0], quaternions[1], quaternions[2], new Cesium.Quaternion());
- * var q = Cesium.Quaternion.squad(quaternions[0], quaternions[1], quaternions[0], s1, t, new Cesium.Quaternion());
- *
- * @see Quaternion#computeInnerQuadrangle
- */
- Quaternion.squad = function (q0, q1, s0, s1, t, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("q0", q0);
- Check.Check.typeOf.object("q1", q1);
- Check.Check.typeOf.object("s0", s0);
- Check.Check.typeOf.object("s1", s1);
- Check.Check.typeOf.number("t", t);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- var slerp0 = Quaternion.slerp(q0, q1, t, squadScratchQuaternion0);
- var slerp1 = Quaternion.slerp(s0, s1, t, squadScratchQuaternion1);
- return Quaternion.slerp(slerp0, slerp1, 2.0 * t * (1.0 - t), result);
- };
- var fastSlerpScratchQuaternion = new Quaternion();
- var opmu = 1.90110745351730037;
- var u = FeatureDetection.supportsTypedArrays() ? new Float32Array(8) : [];
- var v = FeatureDetection.supportsTypedArrays() ? new Float32Array(8) : [];
- var bT = FeatureDetection.supportsTypedArrays() ? new Float32Array(8) : [];
- var bD = FeatureDetection.supportsTypedArrays() ? new Float32Array(8) : [];
- for (var i = 0; i < 7; ++i) {
- var s = i + 1.0;
- var t = 2.0 * s + 1.0;
- u[i] = 1.0 / (s * t);
- v[i] = s / t;
- }
- u[7] = opmu / (8.0 * 17.0);
- v[7] = (opmu * 8.0) / 17.0;
- /**
- * Computes the spherical linear interpolation or extrapolation at t using the provided quaternions.
- * This implementation is faster than {@link Quaternion#slerp}, but is only accurate up to 10<sup>-6</sup>.
- *
- * @param {Quaternion} start The value corresponding to t at 0.0.
- * @param {Quaternion} end The value corresponding to t at 1.0.
- * @param {Number} t The point along t at which to interpolate.
- * @param {Quaternion} result The object onto which to store the result.
- * @returns {Quaternion} The modified result parameter.
- *
- * @see Quaternion#slerp
- */
- Quaternion.fastSlerp = function (start, end, t, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("start", start);
- Check.Check.typeOf.object("end", end);
- Check.Check.typeOf.number("t", t);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- var x = Quaternion.dot(start, end);
- var sign;
- if (x >= 0) {
- sign = 1.0;
- } else {
- sign = -1.0;
- x = -x;
- }
- var xm1 = x - 1.0;
- var d = 1.0 - t;
- var sqrT = t * t;
- var sqrD = d * d;
- for (var i = 7; i >= 0; --i) {
- bT[i] = (u[i] * sqrT - v[i]) * xm1;
- bD[i] = (u[i] * sqrD - v[i]) * xm1;
- }
- var cT =
- sign *
- t *
- (1.0 +
- bT[0] *
- (1.0 +
- bT[1] *
- (1.0 +
- bT[2] *
- (1.0 +
- bT[3] *
- (1.0 +
- bT[4] *
- (1.0 + bT[5] * (1.0 + bT[6] * (1.0 + bT[7]))))))));
- var cD =
- d *
- (1.0 +
- bD[0] *
- (1.0 +
- bD[1] *
- (1.0 +
- bD[2] *
- (1.0 +
- bD[3] *
- (1.0 +
- bD[4] *
- (1.0 + bD[5] * (1.0 + bD[6] * (1.0 + bD[7]))))))));
- var temp = Quaternion.multiplyByScalar(start, cD, fastSlerpScratchQuaternion);
- Quaternion.multiplyByScalar(end, cT, result);
- return Quaternion.add(temp, result, result);
- };
- /**
- * Computes the spherical quadrangle interpolation between quaternions.
- * An implementation that is faster than {@link Quaternion#squad}, but less accurate.
- *
- * @param {Quaternion} q0 The first quaternion.
- * @param {Quaternion} q1 The second quaternion.
- * @param {Quaternion} s0 The first inner quadrangle.
- * @param {Quaternion} s1 The second inner quadrangle.
- * @param {Number} t The time in [0,1] used to interpolate.
- * @param {Quaternion} result The object onto which to store the result.
- * @returns {Quaternion} The modified result parameter or a new instance if none was provided.
- *
- * @see Quaternion#squad
- */
- Quaternion.fastSquad = function (q0, q1, s0, s1, t, result) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("q0", q0);
- Check.Check.typeOf.object("q1", q1);
- Check.Check.typeOf.object("s0", s0);
- Check.Check.typeOf.object("s1", s1);
- Check.Check.typeOf.number("t", t);
- Check.Check.typeOf.object("result", result);
- //>>includeEnd('debug');
- var slerp0 = Quaternion.fastSlerp(q0, q1, t, squadScratchQuaternion0);
- var slerp1 = Quaternion.fastSlerp(s0, s1, t, squadScratchQuaternion1);
- return Quaternion.fastSlerp(slerp0, slerp1, 2.0 * t * (1.0 - t), result);
- };
- /**
- * Compares the provided quaternions componentwise and returns
- * <code>true</code> if they are equal, <code>false</code> otherwise.
- *
- * @param {Quaternion} [left] The first quaternion.
- * @param {Quaternion} [right] The second quaternion.
- * @returns {Boolean} <code>true</code> if left and right are equal, <code>false</code> otherwise.
- */
- Quaternion.equals = function (left, right) {
- return (
- left === right ||
- (when.defined(left) &&
- when.defined(right) &&
- left.x === right.x &&
- left.y === right.y &&
- left.z === right.z &&
- left.w === right.w)
- );
- };
- /**
- * Compares the provided quaternions componentwise and returns
- * <code>true</code> if they are within the provided epsilon,
- * <code>false</code> otherwise.
- *
- * @param {Quaternion} [left] The first quaternion.
- * @param {Quaternion} [right] The second quaternion.
- * @param {Number} [epsilon=0] The epsilon to use for equality testing.
- * @returns {Boolean} <code>true</code> if left and right are within the provided epsilon, <code>false</code> otherwise.
- */
- Quaternion.equalsEpsilon = function (left, right, epsilon) {
- epsilon = when.defaultValue(epsilon, 0);
- return (
- left === right ||
- (when.defined(left) &&
- when.defined(right) &&
- Math.abs(left.x - right.x) <= epsilon &&
- Math.abs(left.y - right.y) <= epsilon &&
- Math.abs(left.z - right.z) <= epsilon &&
- Math.abs(left.w - right.w) <= epsilon)
- );
- };
- /**
- * An immutable Quaternion instance initialized to (0.0, 0.0, 0.0, 0.0).
- *
- * @type {Quaternion}
- * @constant
- */
- Quaternion.ZERO = Object.freeze(new Quaternion(0.0, 0.0, 0.0, 0.0));
- /**
- * An immutable Quaternion instance initialized to (0.0, 0.0, 0.0, 1.0).
- *
- * @type {Quaternion}
- * @constant
- */
- Quaternion.IDENTITY = Object.freeze(new Quaternion(0.0, 0.0, 0.0, 1.0));
- /**
- * Duplicates this Quaternion instance.
- *
- * @param {Quaternion} [result] The object onto which to store the result.
- * @returns {Quaternion} The modified result parameter or a new Quaternion instance if one was not provided.
- */
- Quaternion.prototype.clone = function (result) {
- return Quaternion.clone(this, result);
- };
- /**
- * Compares this and the provided quaternion componentwise and returns
- * <code>true</code> if they are equal, <code>false</code> otherwise.
- *
- * @param {Quaternion} [right] The right hand side quaternion.
- * @returns {Boolean} <code>true</code> if left and right are equal, <code>false</code> otherwise.
- */
- Quaternion.prototype.equals = function (right) {
- return Quaternion.equals(this, right);
- };
- /**
- * Compares this and the provided quaternion componentwise and returns
- * <code>true</code> if they are within the provided epsilon,
- * <code>false</code> otherwise.
- *
- * @param {Quaternion} [right] The right hand side quaternion.
- * @param {Number} [epsilon=0] The epsilon to use for equality testing.
- * @returns {Boolean} <code>true</code> if left and right are within the provided epsilon, <code>false</code> otherwise.
- */
- Quaternion.prototype.equalsEpsilon = function (right, epsilon) {
- return Quaternion.equalsEpsilon(this, right, epsilon);
- };
- /**
- * Returns a string representing this quaternion in the format (x, y, z, w).
- *
- * @returns {String} A string representing this Quaternion.
- */
- Quaternion.prototype.toString = function () {
- return "(" + this.x + ", " + this.y + ", " + this.z + ", " + this.w + ")";
- };
- /**
- * Finds an item in a sorted array.
- *
- * @function
- * @param {Array} array The sorted array to search.
- * @param {*} itemToFind The item to find in the array.
- * @param {binarySearchComparator} comparator The function to use to compare the item to
- * elements in the array.
- * @returns {Number} The index of <code>itemToFind</code> in the array, if it exists. If <code>itemToFind</code>
- * does not exist, the return value is a negative number which is the bitwise complement (~)
- * of the index before which the itemToFind should be inserted in order to maintain the
- * sorted order of the array.
- *
- * @example
- * // Create a comparator function to search through an array of numbers.
- * function comparator(a, b) {
- * return a - b;
- * };
- * var numbers = [0, 2, 4, 6, 8];
- * var index = Cesium.binarySearch(numbers, 6, comparator); // 3
- */
- function binarySearch(array, itemToFind, comparator) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.defined("array", array);
- Check.Check.defined("itemToFind", itemToFind);
- Check.Check.defined("comparator", comparator);
- //>>includeEnd('debug');
- var low = 0;
- var high = array.length - 1;
- var i;
- var comparison;
- while (low <= high) {
- i = ~~((low + high) / 2);
- comparison = comparator(array[i], itemToFind);
- if (comparison < 0) {
- low = i + 1;
- continue;
- }
- if (comparison > 0) {
- high = i - 1;
- continue;
- }
- return i;
- }
- return ~(high + 1);
- }
- /**
- * A set of Earth Orientation Parameters (EOP) sampled at a time.
- *
- * @alias EarthOrientationParametersSample
- * @constructor
- *
- * @param {Number} xPoleWander The pole wander about the X axis, in radians.
- * @param {Number} yPoleWander The pole wander about the Y axis, in radians.
- * @param {Number} xPoleOffset The offset to the Celestial Intermediate Pole (CIP) about the X axis, in radians.
- * @param {Number} yPoleOffset The offset to the Celestial Intermediate Pole (CIP) about the Y axis, in radians.
- * @param {Number} ut1MinusUtc The difference in time standards, UT1 - UTC, in seconds.
- *
- * @private
- */
- function EarthOrientationParametersSample(
- xPoleWander,
- yPoleWander,
- xPoleOffset,
- yPoleOffset,
- ut1MinusUtc
- ) {
- /**
- * The pole wander about the X axis, in radians.
- * @type {Number}
- */
- this.xPoleWander = xPoleWander;
- /**
- * The pole wander about the Y axis, in radians.
- * @type {Number}
- */
- this.yPoleWander = yPoleWander;
- /**
- * The offset to the Celestial Intermediate Pole (CIP) about the X axis, in radians.
- * @type {Number}
- */
- this.xPoleOffset = xPoleOffset;
- /**
- * The offset to the Celestial Intermediate Pole (CIP) about the Y axis, in radians.
- * @type {Number}
- */
- this.yPoleOffset = yPoleOffset;
- /**
- * The difference in time standards, UT1 - UTC, in seconds.
- * @type {Number}
- */
- this.ut1MinusUtc = ut1MinusUtc;
- }
- /**
- @license
- sprintf.js from the php.js project - https://github.com/kvz/phpjs
- Directly from https://github.com/kvz/phpjs/blob/master/functions/strings/sprintf.js
- php.js is copyright 2012 Kevin van Zonneveld.
- Portions copyright Brett Zamir (http://brett-zamir.me), Kevin van Zonneveld
- (http://kevin.vanzonneveld.net), Onno Marsman, Theriault, Michael White
- (http://getsprink.com), Waldo Malqui Silva, Paulo Freitas, Jack, Jonas
- Raoni Soares Silva (http://www.jsfromhell.com), Philip Peterson, Legaev
- Andrey, Ates Goral (http://magnetiq.com), Alex, Ratheous, Martijn Wieringa,
- Rafa? Kukawski (http://blog.kukawski.pl), lmeyrick
- (https://sourceforge.net/projects/bcmath-js/), Nate, Philippe Baumann,
- Enrique Gonzalez, Webtoolkit.info (http://www.webtoolkit.info/), Carlos R.
- L. Rodrigues (http://www.jsfromhell.com), Ash Searle
- (http://hexmen.com/blog/), Jani Hartikainen, travc, Ole Vrijenhoek,
- Erkekjetter, Michael Grier, Rafa? Kukawski (http://kukawski.pl), Johnny
- Mast (http://www.phpvrouwen.nl), T.Wild, d3x,
- http://stackoverflow.com/questions/57803/how-to-convert-decimal-to-hex-in-javascript,
- Rafa? Kukawski (http://blog.kukawski.pl/), stag019, pilus, WebDevHobo
- (http://webdevhobo.blogspot.com/), marrtins, GeekFG
- (http://geekfg.blogspot.com), Andrea Giammarchi
- (http://webreflection.blogspot.com), Arpad Ray (mailto:arpad@php.net),
- gorthaur, Paul Smith, Tim de Koning (http://www.kingsquare.nl), Joris, Oleg
- Eremeev, Steve Hilder, majak, gettimeofday, KELAN, Josh Fraser
- (http://onlineaspect.com/2007/06/08/auto-detect-a-time-zone-with-javascript/),
- Marc Palau, Martin
- (http://www.erlenwiese.de/), Breaking Par Consulting Inc
- (http://www.breakingpar.com/bkp/home.nsf/0/87256B280015193F87256CFB006C45F7),
- Chris, Mirek Slugen, saulius, Alfonso Jimenez
- (http://www.alfonsojimenez.com), Diplom@t (http://difane.com/), felix,
- Mailfaker (http://www.weedem.fr/), Tyler Akins (http://rumkin.com), Caio
- Ariede (http://caioariede.com), Robin, Kankrelune
- (http://www.webfaktory.info/), Karol Kowalski, Imgen Tata
- (http://www.myipdf.com/), mdsjack (http://www.mdsjack.bo.it), Dreamer,
- Felix Geisendoerfer (http://www.debuggable.com/felix), Lars Fischer, AJ,
- David, Aman Gupta, Michael White, Public Domain
- (http://www.json.org/json2.js), Steven Levithan
- (http://blog.stevenlevithan.com), Sakimori, Pellentesque Malesuada,
- Thunder.m, Dj (http://phpjs.org/functions/htmlentities:425#comment_134018),
- Steve Clay, David James, Francois, class_exists, nobbler, T. Wild, Itsacon
- (http://www.itsacon.net/), date, Ole Vrijenhoek (http://www.nervous.nl/),
- Fox, Raphael (Ao RUDLER), Marco, noname, Mateusz "loonquawl" Zalega, Frank
- Forte, Arno, ger, mktime, john (http://www.jd-tech.net), Nick Kolosov
- (http://sammy.ru), marc andreu, Scott Cariss, Douglas Crockford
- (http://javascript.crockford.com), madipta, Slawomir Kaniecki,
- ReverseSyntax, Nathan, Alex Wilson, kenneth, Bayron Guevara, Adam Wallner
- (http://web2.bitbaro.hu/), paulo kuong, jmweb, Lincoln Ramsay, djmix,
- Pyerre, Jon Hohle, Thiago Mata (http://thiagomata.blog.com), lmeyrick
- (https://sourceforge.net/projects/bcmath-js/this.), Linuxworld, duncan,
- Gilbert, Sanjoy Roy, Shingo, sankai, Oskar Larsson H?gfeldt
- (http://oskar-lh.name/), Denny Wardhana, 0m3r, Everlasto, Subhasis Deb,
- josh, jd, Pier Paolo Ramon (http://www.mastersoup.com/), P, merabi, Soren
- Hansen, Eugene Bulkin (http://doubleaw.com/), Der Simon
- (http://innerdom.sourceforge.net/), echo is bad, Ozh, XoraX
- (http://www.xorax.info), EdorFaus, JB, J A R, Marc Jansen, Francesco, LH,
- Stoyan Kyosev (http://www.svest.org/), nord_ua, omid
- (http://phpjs.org/functions/380:380#comment_137122), Brad Touesnard, MeEtc
- (http://yass.meetcweb.com), Peter-Paul Koch
- (http://www.quirksmode.org/js/beat.html), Olivier Louvignes
- (http://mg-crea.com/), T0bsn, Tim Wiel, Bryan Elliott, Jalal Berrami,
- Martin, JT, David Randall, Thomas Beaucourt (http://www.webapp.fr), taith,
- vlado houba, Pierre-Luc Paour, Kristof Coomans (SCK-CEN Belgian Nucleair
- Research Centre), Martin Pool, Kirk Strobeck, Rick Waldron, Brant Messenger
- (http://www.brantmessenger.com/), Devan Penner-Woelk, Saulo Vallory, Wagner
- B. Soares, Artur Tchernychev, Valentina De Rosa, Jason Wong
- (http://carrot.org/), Christoph, Daniel Esteban, strftime, Mick@el, rezna,
- Simon Willison (http://simonwillison.net), Anton Ongson, Gabriel Paderni,
- Marco van Oort, penutbutterjelly, Philipp Lenssen, Bjorn Roesbeke
- (http://www.bjornroesbeke.be/), Bug?, Eric Nagel, Tomasz Wesolowski,
- Evertjan Garretsen, Bobby Drake, Blues (http://tech.bluesmoon.info/), Luke
- Godfrey, Pul, uestla, Alan C, Ulrich, Rafal Kukawski, Yves Sucaet,
- sowberry, Norman "zEh" Fuchs, hitwork, Zahlii, johnrembo, Nick Callen,
- Steven Levithan (stevenlevithan.com), ejsanders, Scott Baker, Brian Tafoya
- (http://www.premasolutions.com/), Philippe Jausions
- (http://pear.php.net/user/jausions), Aidan Lister
- (http://aidanlister.com/), Rob, e-mike, HKM, ChaosNo1, metjay, strcasecmp,
- strcmp, Taras Bogach, jpfle, Alexander Ermolaev
- (http://snippets.dzone.com/user/AlexanderErmolaev), DxGx, kilops, Orlando,
- dptr1988, Le Torbi, James (http://www.james-bell.co.uk/), Pedro Tainha
- (http://www.pedrotainha.com), James, Arnout Kazemier
- (http://www.3rd-Eden.com), Chris McMacken, gabriel paderni, Yannoo,
- FGFEmperor, baris ozdil, Tod Gentille, Greg Frazier, jakes, 3D-GRAF, Allan
- Jensen (http://www.winternet.no), Howard Yeend, Benjamin Lupton, davook,
- daniel airton wermann (http://wermann.com.br), Atli T¨®r, Maximusya, Ryan
- W Tenney (http://ryan.10e.us), Alexander M Beedie, fearphage
- (http://http/my.opera.com/fearphage/), Nathan Sepulveda, Victor, Matteo,
- Billy, stensi, Cord, Manish, T.J. Leahy, Riddler
- (http://www.frontierwebdev.com/), Rafa? Kukawski, FremyCompany, Matt
- Bradley, Tim de Koning, Luis Salazar (http://www.freaky-media.com/), Diogo
- Resende, Rival, Andrej Pavlovic, Garagoth, Le Torbi
- (http://www.letorbi.de/), Dino, Josep Sanz (http://www.ws3.es/), rem,
- Russell Walker (http://www.nbill.co.uk/), Jamie Beck
- (http://www.terabit.ca/), setcookie, Michael, YUI Library:
- http://developer.yahoo.com/yui/docs/YAHOO.util.DateLocale.html, Blues at
- http://hacks.bluesmoon.info/strftime/strftime.js, Ben
- (http://benblume.co.uk/), DtTvB
- (http://dt.in.th/2008-09-16.string-length-in-bytes.html), Andreas, William,
- meo, incidence, Cagri Ekin, Amirouche, Amir Habibi
- (http://www.residence-mixte.com/), Luke Smith (http://lucassmith.name),
- Kheang Hok Chin (http://www.distantia.ca/), Jay Klehr, Lorenzo Pisani,
- Tony, Yen-Wei Liu, Greenseed, mk.keck, Leslie Hoare, dude, booeyOH, Ben
- Bryan
- Licensed under the MIT (MIT-LICENSE.txt) license.
- Permission is hereby granted, free of charge, to any person obtaining a
- copy of this software and associated documentation files (the
- "Software"), to deal in the Software without restriction, including
- without limitation the rights to use, copy, modify, merge, publish,
- distribute, sublicense, and/or sell copies of the Software, and to
- permit persons to whom the Software is furnished to do so, subject to
- the following conditions:
- The above copyright notice and this permission notice shall be included
- in all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- IN NO EVENT SHALL KEVIN VAN ZONNEVELD BE LIABLE FOR ANY CLAIM, DAMAGES
- OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- OTHER DEALINGS IN THE SOFTWARE.
- */
- function sprintf () {
- // http://kevin.vanzonneveld.net
- // + original by: Ash Searle (http://hexmen.com/blog/)
- // + namespaced by: Michael White (http://getsprink.com)
- // + tweaked by: Jack
- // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
- // + input by: Paulo Freitas
- // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
- // + input by: Brett Zamir (http://brett-zamir.me)
- // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
- // + improved by: Dj
- // + improved by: Allidylls
- // * example 1: sprintf("%01.2f", 123.1);
- // * returns 1: 123.10
- // * example 2: sprintf("[%10s]", 'monkey');
- // * returns 2: '[ monkey]'
- // * example 3: sprintf("[%'#10s]", 'monkey');
- // * returns 3: '[####monkey]'
- // * example 4: sprintf("%d", 123456789012345);
- // * returns 4: '123456789012345'
- var regex = /%%|%(\d+\$)?([-+\'#0 ]*)(\*\d+\$|\*|\d+)?(\.(\*\d+\$|\*|\d+))?([scboxXuideEfFgG])/g;
- var a = arguments,
- i = 0,
- format = a[i++];
- // pad()
- var pad = function (str, len, chr, leftJustify) {
- if (!chr) {
- chr = ' ';
- }
- var padding = (str.length >= len) ? '' : Array(1 + len - str.length >>> 0).join(chr);
- return leftJustify ? str + padding : padding + str;
- };
- // justify()
- var justify = function (value, prefix, leftJustify, minWidth, zeroPad, customPadChar) {
- var diff = minWidth - value.length;
- if (diff > 0) {
- if (leftJustify || !zeroPad) {
- value = pad(value, minWidth, customPadChar, leftJustify);
- } else {
- value = value.slice(0, prefix.length) + pad('', diff, '0', true) + value.slice(prefix.length);
- }
- }
- return value;
- };
- // formatBaseX()
- var formatBaseX = function (value, base, prefix, leftJustify, minWidth, precision, zeroPad) {
- // Note: casts negative numbers to positive ones
- var number = value >>> 0;
- prefix = prefix && number && {
- '2': '0b',
- '8': '0',
- '16': '0x'
- }[base] || '';
- value = prefix + pad(number.toString(base), precision || 0, '0', false);
- return justify(value, prefix, leftJustify, minWidth, zeroPad);
- };
- // formatString()
- var formatString = function (value, leftJustify, minWidth, precision, zeroPad, customPadChar) {
- if (precision != null) {
- value = value.slice(0, precision);
- }
- return justify(value, '', leftJustify, minWidth, zeroPad, customPadChar);
- };
- // doFormat()
- var doFormat = function (substring, valueIndex, flags, minWidth, _, precision, type) {
- var number;
- var prefix;
- var method;
- var textTransform;
- var value;
- if (substring == '%%') {
- return '%';
- }
- // parse flags
- var leftJustify = false,
- positivePrefix = '',
- zeroPad = false,
- prefixBaseX = false,
- customPadChar = ' ';
- var flagsl = flags.length;
- for (var j = 0; flags && j < flagsl; j++) {
- switch (flags.charAt(j)) {
- case ' ':
- positivePrefix = ' ';
- break;
- case '+':
- positivePrefix = '+';
- break;
- case '-':
- leftJustify = true;
- break;
- case "'":
- customPadChar = flags.charAt(j + 1);
- break;
- case '0':
- zeroPad = true;
- break;
- case '#':
- prefixBaseX = true;
- break;
- }
- }
- // parameters may be null, undefined, empty-string or real valued
- // we want to ignore null, undefined and empty-string values
- if (!minWidth) {
- minWidth = 0;
- } else if (minWidth == '*') {
- minWidth = +a[i++];
- } else if (minWidth.charAt(0) == '*') {
- minWidth = +a[minWidth.slice(1, -1)];
- } else {
- minWidth = +minWidth;
- }
- // Note: undocumented perl feature:
- if (minWidth < 0) {
- minWidth = -minWidth;
- leftJustify = true;
- }
- if (!isFinite(minWidth)) {
- throw new Error('sprintf: (minimum-)width must be finite');
- }
- if (!precision) {
- precision = 'fFeE'.indexOf(type) > -1 ? 6 : (type == 'd') ? 0 : undefined;
- } else if (precision == '*') {
- precision = +a[i++];
- } else if (precision.charAt(0) == '*') {
- precision = +a[precision.slice(1, -1)];
- } else {
- precision = +precision;
- }
- // grab value using valueIndex if required?
- value = valueIndex ? a[valueIndex.slice(0, -1)] : a[i++];
- switch (type) {
- case 's':
- return formatString(String(value), leftJustify, minWidth, precision, zeroPad, customPadChar);
- case 'c':
- return formatString(String.fromCharCode(+value), leftJustify, minWidth, precision, zeroPad);
- case 'b':
- return formatBaseX(value, 2, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
- case 'o':
- return formatBaseX(value, 8, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
- case 'x':
- return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
- case 'X':
- return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad).toUpperCase();
- case 'u':
- return formatBaseX(value, 10, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
- case 'i':
- case 'd':
- number = +value || 0;
- number = Math.round(number - number % 1); // Plain Math.round doesn't just truncate
- prefix = number < 0 ? '-' : positivePrefix;
- value = prefix + pad(String(Math.abs(number)), precision, '0', false);
- return justify(value, prefix, leftJustify, minWidth, zeroPad);
- case 'e':
- case 'E':
- case 'f': // Should handle locales (as per setlocale)
- case 'F':
- case 'g':
- case 'G':
- number = +value;
- prefix = number < 0 ? '-' : positivePrefix;
- method = ['toExponential', 'toFixed', 'toPrecision']['efg'.indexOf(type.toLowerCase())];
- textTransform = ['toString', 'toUpperCase']['eEfFgG'.indexOf(type) % 2];
- value = prefix + Math.abs(number)[method](precision);
- return justify(value, prefix, leftJustify, minWidth, zeroPad)[textTransform]();
- default:
- return substring;
- }
- };
- return format.replace(regex, doFormat);
- }
- /**
- * Represents a Gregorian date in a more precise format than the JavaScript Date object.
- * In addition to submillisecond precision, this object can also represent leap seconds.
- * @alias GregorianDate
- * @constructor
- *
- * @param {Number} [year] The year as a whole number.
- * @param {Number} [month] The month as a whole number with range [1, 12].
- * @param {Number} [day] The day of the month as a whole number starting at 1.
- * @param {Number} [hour] The hour as a whole number with range [0, 23].
- * @param {Number} [minute] The minute of the hour as a whole number with range [0, 59].
- * @param {Number} [second] The second of the minute as a whole number with range [0, 60], with 60 representing a leap second.
- * @param {Number} [millisecond] The millisecond of the second as a floating point number with range [0.0, 1000.0).
- * @param {Boolean} [isLeapSecond] Whether this time is during a leap second.
- *
- * @see JulianDate#toGregorianDate
- */
- function GregorianDate(
- year,
- month,
- day,
- hour,
- minute,
- second,
- millisecond,
- isLeapSecond
- ) {
- /**
- * Gets or sets the year as a whole number.
- * @type {Number}
- */
- this.year = year;
- /**
- * Gets or sets the month as a whole number with range [1, 12].
- * @type {Number}
- */
- this.month = month;
- /**
- * Gets or sets the day of the month as a whole number starting at 1.
- * @type {Number}
- */
- this.day = day;
- /**
- * Gets or sets the hour as a whole number with range [0, 23].
- * @type {Number}
- */
- this.hour = hour;
- /**
- * Gets or sets the minute of the hour as a whole number with range [0, 59].
- * @type {Number}
- */
- this.minute = minute;
- /**
- * Gets or sets the second of the minute as a whole number with range [0, 60], with 60 representing a leap second.
- * @type {Number}
- */
- this.second = second;
- /**
- * Gets or sets the millisecond of the second as a floating point number with range [0.0, 1000.0).
- * @type {Number}
- */
- this.millisecond = millisecond;
- /**
- * Gets or sets whether this time is during a leap second.
- * @type {Boolean}
- */
- this.isLeapSecond = isLeapSecond;
- }
- /**
- * Determines if a given date is a leap year.
- *
- * @function isLeapYear
- *
- * @param {Number} year The year to be tested.
- * @returns {Boolean} True if <code>year</code> is a leap year.
- *
- * @example
- * var leapYear = Cesium.isLeapYear(2000); // true
- */
- function isLeapYear(year) {
- //>>includeStart('debug', pragmas.debug);
- if (year === null || isNaN(year)) {
- throw new Check.DeveloperError("year is required and must be a number.");
- }
- //>>includeEnd('debug');
- return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
- }
- /**
- * Describes a single leap second, which is constructed from a {@link JulianDate} and a
- * numerical offset representing the number of seconds TAI is ahead of the UTC time standard.
- * @alias LeapSecond
- * @constructor
- *
- * @param {JulianDate} [date] A Julian date representing the time of the leap second.
- * @param {Number} [offset] The cumulative number of seconds that TAI is ahead of UTC at the provided date.
- */
- function LeapSecond(date, offset) {
- /**
- * Gets or sets the date at which this leap second occurs.
- * @type {JulianDate}
- */
- this.julianDate = date;
- /**
- * Gets or sets the cumulative number of seconds between the UTC and TAI time standards at the time
- * of this leap second.
- * @type {Number}
- */
- this.offset = offset;
- }
- /**
- * Constants for time conversions like those done by {@link JulianDate}.
- *
- * @namespace TimeConstants
- *
- * @see JulianDate
- *
- * @private
- */
- var TimeConstants = {
- /**
- * The number of seconds in one millisecond: <code>0.001</code>
- * @type {Number}
- * @constant
- */
- SECONDS_PER_MILLISECOND: 0.001,
- /**
- * The number of seconds in one minute: <code>60</code>.
- * @type {Number}
- * @constant
- */
- SECONDS_PER_MINUTE: 60.0,
- /**
- * The number of minutes in one hour: <code>60</code>.
- * @type {Number}
- * @constant
- */
- MINUTES_PER_HOUR: 60.0,
- /**
- * The number of hours in one day: <code>24</code>.
- * @type {Number}
- * @constant
- */
- HOURS_PER_DAY: 24.0,
- /**
- * The number of seconds in one hour: <code>3600</code>.
- * @type {Number}
- * @constant
- */
- SECONDS_PER_HOUR: 3600.0,
- /**
- * The number of minutes in one day: <code>1440</code>.
- * @type {Number}
- * @constant
- */
- MINUTES_PER_DAY: 1440.0,
- /**
- * The number of seconds in one day, ignoring leap seconds: <code>86400</code>.
- * @type {Number}
- * @constant
- */
- SECONDS_PER_DAY: 86400.0,
- /**
- * The number of days in one Julian century: <code>36525</code>.
- * @type {Number}
- * @constant
- */
- DAYS_PER_JULIAN_CENTURY: 36525.0,
- /**
- * One trillionth of a second.
- * @type {Number}
- * @constant
- */
- PICOSECOND: 0.000000001,
- /**
- * The number of days to subtract from a Julian date to determine the
- * modified Julian date, which gives the number of days since midnight
- * on November 17, 1858.
- * @type {Number}
- * @constant
- */
- MODIFIED_JULIAN_DATE_DIFFERENCE: 2400000.5,
- };
- var TimeConstants$1 = Object.freeze(TimeConstants);
- /**
- * Provides the type of time standards which JulianDate can take as input.
- *
- * @enum {Number}
- *
- * @see JulianDate
- */
- var TimeStandard = {
- /**
- * Represents the coordinated Universal Time (UTC) time standard.
- *
- * UTC is related to TAI according to the relationship
- * <code>UTC = TAI - deltaT</code> where <code>deltaT</code> is the number of leap
- * seconds which have been introduced as of the time in TAI.
- *
- * @type {Number}
- * @constant
- */
- UTC: 0,
- /**
- * Represents the International Atomic Time (TAI) time standard.
- * TAI is the principal time standard to which the other time standards are related.
- *
- * @type {Number}
- * @constant
- */
- TAI: 1,
- };
- var TimeStandard$1 = Object.freeze(TimeStandard);
- var gregorianDateScratch = new GregorianDate();
- var daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
- var daysInLeapFeburary = 29;
- function compareLeapSecondDates(leapSecond, dateToFind) {
- return JulianDate.compare(leapSecond.julianDate, dateToFind.julianDate);
- }
- // we don't really need a leap second instance, anything with a julianDate property will do
- var binarySearchScratchLeapSecond = new LeapSecond();
- function convertUtcToTai(julianDate) {
- //Even though julianDate is in UTC, we'll treat it as TAI and
- //search the leap second table for it.
- binarySearchScratchLeapSecond.julianDate = julianDate;
- var leapSeconds = JulianDate.leapSeconds;
- var index = binarySearch(
- leapSeconds,
- binarySearchScratchLeapSecond,
- compareLeapSecondDates
- );
- if (index < 0) {
- index = ~index;
- }
- if (index >= leapSeconds.length) {
- index = leapSeconds.length - 1;
- }
- var offset = leapSeconds[index].offset;
- if (index > 0) {
- //Now we have the index of the closest leap second that comes on or after our UTC time.
- //However, if the difference between the UTC date being converted and the TAI
- //defined leap second is greater than the offset, we are off by one and need to use
- //the previous leap second.
- var difference = JulianDate.secondsDifference(
- leapSeconds[index].julianDate,
- julianDate
- );
- if (difference > offset) {
- index--;
- offset = leapSeconds[index].offset;
- }
- }
- JulianDate.addSeconds(julianDate, offset, julianDate);
- }
- function convertTaiToUtc(julianDate, result) {
- binarySearchScratchLeapSecond.julianDate = julianDate;
- var leapSeconds = JulianDate.leapSeconds;
- var index = binarySearch(
- leapSeconds,
- binarySearchScratchLeapSecond,
- compareLeapSecondDates
- );
- if (index < 0) {
- index = ~index;
- }
- //All times before our first leap second get the first offset.
- if (index === 0) {
- return JulianDate.addSeconds(julianDate, -leapSeconds[0].offset, result);
- }
- //All times after our leap second get the last offset.
- if (index >= leapSeconds.length) {
- return JulianDate.addSeconds(
- julianDate,
- -leapSeconds[index - 1].offset,
- result
- );
- }
- //Compute the difference between the found leap second and the time we are converting.
- var difference = JulianDate.secondsDifference(
- leapSeconds[index].julianDate,
- julianDate
- );
- if (difference === 0) {
- //The date is in our leap second table.
- return JulianDate.addSeconds(
- julianDate,
- -leapSeconds[index].offset,
- result
- );
- }
- if (difference <= 1.0) {
- //The requested date is during the moment of a leap second, then we cannot convert to UTC
- return undefined;
- }
- //The time is in between two leap seconds, index is the leap second after the date
- //we're converting, so we subtract one to get the correct LeapSecond instance.
- return JulianDate.addSeconds(
- julianDate,
- -leapSeconds[--index].offset,
- result
- );
- }
- function setComponents(wholeDays, secondsOfDay, julianDate) {
- var extraDays = (secondsOfDay / TimeConstants$1.SECONDS_PER_DAY) | 0;
- wholeDays += extraDays;
- secondsOfDay -= TimeConstants$1.SECONDS_PER_DAY * extraDays;
- if (secondsOfDay < 0) {
- wholeDays--;
- secondsOfDay += TimeConstants$1.SECONDS_PER_DAY;
- }
- julianDate.dayNumber = wholeDays;
- julianDate.secondsOfDay = secondsOfDay;
- return julianDate;
- }
- function computeJulianDateComponents(
- year,
- month,
- day,
- hour,
- minute,
- second,
- millisecond
- ) {
- // Algorithm from page 604 of the Explanatory Supplement to the
- // Astronomical Almanac (Seidelmann 1992).
- var a = ((month - 14) / 12) | 0;
- var b = year + 4800 + a;
- var dayNumber =
- (((1461 * b) / 4) | 0) +
- (((367 * (month - 2 - 12 * a)) / 12) | 0) -
- (((3 * (((b + 100) / 100) | 0)) / 4) | 0) +
- day -
- 32075;
- // JulianDates are noon-based
- hour = hour - 12;
- if (hour < 0) {
- hour += 24;
- }
- var secondsOfDay =
- second +
- (hour * TimeConstants$1.SECONDS_PER_HOUR +
- minute * TimeConstants$1.SECONDS_PER_MINUTE +
- millisecond * TimeConstants$1.SECONDS_PER_MILLISECOND);
- if (secondsOfDay >= 43200.0) {
- dayNumber -= 1;
- }
- return [dayNumber, secondsOfDay];
- }
- //Regular expressions used for ISO8601 date parsing.
- //YYYY
- var matchCalendarYear = /^(\d{4})$/;
- //YYYY-MM (YYYYMM is invalid)
- var matchCalendarMonth = /^(\d{4})-(\d{2})$/;
- //YYYY-DDD or YYYYDDD
- var matchOrdinalDate = /^(\d{4})-?(\d{3})$/;
- //YYYY-Www or YYYYWww or YYYY-Www-D or YYYYWwwD
- var matchWeekDate = /^(\d{4})-?W(\d{2})-?(\d{1})?$/;
- //YYYY-MM-DD or YYYYMMDD
- var matchCalendarDate = /^(\d{4})-?(\d{2})-?(\d{2})$/;
- // Match utc offset
- var utcOffset = /([Z+\-])?(\d{2})?:?(\d{2})?$/;
- // Match hours HH or HH.xxxxx
- var matchHours = /^(\d{2})(\.\d+)?/.source + utcOffset.source;
- // Match hours/minutes HH:MM HHMM.xxxxx
- var matchHoursMinutes = /^(\d{2}):?(\d{2})(\.\d+)?/.source + utcOffset.source;
- // Match hours/minutes HH:MM:SS HHMMSS.xxxxx
- var matchHoursMinutesSeconds =
- /^(\d{2}):?(\d{2}):?(\d{2})(\.\d+)?/.source + utcOffset.source;
- var iso8601ErrorMessage = "Invalid ISO 8601 date.";
- /**
- * Represents an astronomical Julian date, which is the number of days since noon on January 1, -4712 (4713 BC).
- * For increased precision, this class stores the whole number part of the date and the seconds
- * part of the date in separate components. In order to be safe for arithmetic and represent
- * leap seconds, the date is always stored in the International Atomic Time standard
- * {@link TimeStandard.TAI}.
- * @alias JulianDate
- * @constructor
- *
- * @param {Number} [julianDayNumber=0.0] The Julian Day Number representing the number of whole days. Fractional days will also be handled correctly.
- * @param {Number} [secondsOfDay=0.0] The number of seconds into the current Julian Day Number. Fractional seconds, negative seconds and seconds greater than a day will be handled correctly.
- * @param {TimeStandard} [timeStandard=TimeStandard.UTC] The time standard in which the first two parameters are defined.
- */
- function JulianDate(julianDayNumber, secondsOfDay, timeStandard) {
- /**
- * Gets or sets the number of whole days.
- * @type {Number}
- */
- this.dayNumber = undefined;
- /**
- * Gets or sets the number of seconds into the current day.
- * @type {Number}
- */
- this.secondsOfDay = undefined;
- julianDayNumber = when.defaultValue(julianDayNumber, 0.0);
- secondsOfDay = when.defaultValue(secondsOfDay, 0.0);
- timeStandard = when.defaultValue(timeStandard, TimeStandard$1.UTC);
- //If julianDayNumber is fractional, make it an integer and add the number of seconds the fraction represented.
- var wholeDays = julianDayNumber | 0;
- secondsOfDay =
- secondsOfDay +
- (julianDayNumber - wholeDays) * TimeConstants$1.SECONDS_PER_DAY;
- setComponents(wholeDays, secondsOfDay, this);
- if (timeStandard === TimeStandard$1.UTC) {
- convertUtcToTai(this);
- }
- }
- /**
- * Creates a new instance from a GregorianDate.
- *
- * @param {GregorianDate} date A GregorianDate.
- * @param {JulianDate} [result] An existing instance to use for the result.
- * @returns {JulianDate} The modified result parameter or a new instance if none was provided.
- *
- * @exception {DeveloperError} date must be a valid GregorianDate.
- */
- JulianDate.fromGregorianDate = function (date, result) {
- //>>includeStart('debug', pragmas.debug);
- if (!(date instanceof GregorianDate)) {
- throw new Check.DeveloperError("date must be a valid GregorianDate.");
- }
- //>>includeEnd('debug');
- var components = computeJulianDateComponents(
- date.year,
- date.month,
- date.day,
- date.hour,
- date.minute,
- date.second,
- date.millisecond
- );
- if (!when.defined(result)) {
- return new JulianDate(components[0], components[1], TimeStandard$1.UTC);
- }
- setComponents(components[0], components[1], result);
- convertUtcToTai(result);
- return result;
- };
- /**
- * Creates a new instance from a JavaScript Date.
- *
- * @param {Date} date A JavaScript Date.
- * @param {JulianDate} [result] An existing instance to use for the result.
- * @returns {JulianDate} The modified result parameter or a new instance if none was provided.
- *
- * @exception {DeveloperError} date must be a valid JavaScript Date.
- */
- JulianDate.fromDate = function (date, result) {
- //>>includeStart('debug', pragmas.debug);
- if (!(date instanceof Date) || isNaN(date.getTime())) {
- throw new Check.DeveloperError("date must be a valid JavaScript Date.");
- }
- //>>includeEnd('debug');
- var components = computeJulianDateComponents(
- date.getUTCFullYear(),
- date.getUTCMonth() + 1,
- date.getUTCDate(),
- date.getUTCHours(),
- date.getUTCMinutes(),
- date.getUTCSeconds(),
- date.getUTCMilliseconds()
- );
- if (!when.defined(result)) {
- return new JulianDate(components[0], components[1], TimeStandard$1.UTC);
- }
- setComponents(components[0], components[1], result);
- convertUtcToTai(result);
- return result;
- };
- /**
- * Creates a new instance from a from an {@link http://en.wikipedia.org/wiki/ISO_8601|ISO 8601} date.
- * This method is superior to <code>Date.parse</code> because it will handle all valid formats defined by the ISO 8601
- * specification, including leap seconds and sub-millisecond times, which discarded by most JavaScript implementations.
- *
- * @param {String} iso8601String An ISO 8601 date.
- * @param {JulianDate} [result] An existing instance to use for the result.
- * @returns {JulianDate} The modified result parameter or a new instance if none was provided.
- *
- * @exception {DeveloperError} Invalid ISO 8601 date.
- */
- JulianDate.fromIso8601 = function (iso8601String, result) {
- //>>includeStart('debug', pragmas.debug);
- if (typeof iso8601String !== "string") {
- throw new Check.DeveloperError(iso8601ErrorMessage);
- }
- //>>includeEnd('debug');
- //Comma and decimal point both indicate a fractional number according to ISO 8601,
- //start out by blanket replacing , with . which is the only valid such symbol in JS.
- iso8601String = iso8601String.replace(",", ".");
- //Split the string into its date and time components, denoted by a mandatory T
- var tokens = iso8601String.split("T");
- var year;
- var month = 1;
- var day = 1;
- var hour = 0;
- var minute = 0;
- var second = 0;
- var millisecond = 0;
- //Lacking a time is okay, but a missing date is illegal.
- var date = tokens[0];
- var time = tokens[1];
- var tmp;
- var inLeapYear;
- //>>includeStart('debug', pragmas.debug);
- if (!when.defined(date)) {
- throw new Check.DeveloperError(iso8601ErrorMessage);
- }
- var dashCount;
- //>>includeEnd('debug');
- //First match the date against possible regular expressions.
- tokens = date.match(matchCalendarDate);
- if (tokens !== null) {
- //>>includeStart('debug', pragmas.debug);
- dashCount = date.split("-").length - 1;
- if (dashCount > 0 && dashCount !== 2) {
- throw new Check.DeveloperError(iso8601ErrorMessage);
- }
- //>>includeEnd('debug');
- year = +tokens[1];
- month = +tokens[2];
- day = +tokens[3];
- } else {
- tokens = date.match(matchCalendarMonth);
- if (tokens !== null) {
- year = +tokens[1];
- month = +tokens[2];
- } else {
- tokens = date.match(matchCalendarYear);
- if (tokens !== null) {
- year = +tokens[1];
- } else {
- //Not a year/month/day so it must be an ordinal date.
- var dayOfYear;
- tokens = date.match(matchOrdinalDate);
- if (tokens !== null) {
- year = +tokens[1];
- dayOfYear = +tokens[2];
- inLeapYear = isLeapYear(year);
- //This validation is only applicable for this format.
- //>>includeStart('debug', pragmas.debug);
- if (
- dayOfYear < 1 ||
- (inLeapYear && dayOfYear > 366) ||
- (!inLeapYear && dayOfYear > 365)
- ) {
- throw new Check.DeveloperError(iso8601ErrorMessage);
- }
- //>>includeEnd('debug')
- } else {
- tokens = date.match(matchWeekDate);
- if (tokens !== null) {
- //ISO week date to ordinal date from
- //http://en.wikipedia.org/w/index.php?title=ISO_week_date&oldid=474176775
- year = +tokens[1];
- var weekNumber = +tokens[2];
- var dayOfWeek = +tokens[3] || 0;
- //>>includeStart('debug', pragmas.debug);
- dashCount = date.split("-").length - 1;
- if (
- dashCount > 0 &&
- ((!when.defined(tokens[3]) && dashCount !== 1) ||
- (when.defined(tokens[3]) && dashCount !== 2))
- ) {
- throw new Check.DeveloperError(iso8601ErrorMessage);
- }
- //>>includeEnd('debug')
- var january4 = new Date(Date.UTC(year, 0, 4));
- dayOfYear = weekNumber * 7 + dayOfWeek - january4.getUTCDay() - 3;
- } else {
- //None of our regular expressions succeeded in parsing the date properly.
- //>>includeStart('debug', pragmas.debug);
- throw new Check.DeveloperError(iso8601ErrorMessage);
- //>>includeEnd('debug')
- }
- }
- //Split an ordinal date into month/day.
- tmp = new Date(Date.UTC(year, 0, 1));
- tmp.setUTCDate(dayOfYear);
- month = tmp.getUTCMonth() + 1;
- day = tmp.getUTCDate();
- }
- }
- }
- //Now that we have all of the date components, validate them to make sure nothing is out of range.
- inLeapYear = isLeapYear(year);
- //>>includeStart('debug', pragmas.debug);
- if (
- month < 1 ||
- month > 12 ||
- day < 1 ||
- ((month !== 2 || !inLeapYear) && day > daysInMonth[month - 1]) ||
- (inLeapYear && month === 2 && day > daysInLeapFeburary)
- ) {
- throw new Check.DeveloperError(iso8601ErrorMessage);
- }
- //>>includeEnd('debug')
- //Now move onto the time string, which is much simpler.
- //If no time is specified, it is considered the beginning of the day, UTC to match Javascript's implementation.
- var offsetIndex;
- if (when.defined(time)) {
- tokens = time.match(matchHoursMinutesSeconds);
- if (tokens !== null) {
- //>>includeStart('debug', pragmas.debug);
- dashCount = time.split(":").length - 1;
- if (dashCount > 0 && dashCount !== 2 && dashCount !== 3) {
- throw new Check.DeveloperError(iso8601ErrorMessage);
- }
- //>>includeEnd('debug')
- hour = +tokens[1];
- minute = +tokens[2];
- second = +tokens[3];
- millisecond = +(tokens[4] || 0) * 1000.0;
- offsetIndex = 5;
- } else {
- tokens = time.match(matchHoursMinutes);
- if (tokens !== null) {
- //>>includeStart('debug', pragmas.debug);
- dashCount = time.split(":").length - 1;
- if (dashCount > 2) {
- throw new Check.DeveloperError(iso8601ErrorMessage);
- }
- //>>includeEnd('debug')
- hour = +tokens[1];
- minute = +tokens[2];
- second = +(tokens[3] || 0) * 60.0;
- offsetIndex = 4;
- } else {
- tokens = time.match(matchHours);
- if (tokens !== null) {
- hour = +tokens[1];
- minute = +(tokens[2] || 0) * 60.0;
- offsetIndex = 3;
- } else {
- //>>includeStart('debug', pragmas.debug);
- throw new Check.DeveloperError(iso8601ErrorMessage);
- //>>includeEnd('debug')
- }
- }
- }
- //Validate that all values are in proper range. Minutes and hours have special cases at 60 and 24.
- //>>includeStart('debug', pragmas.debug);
- if (
- minute >= 60 ||
- second >= 61 ||
- hour > 24 ||
- (hour === 24 && (minute > 0 || second > 0 || millisecond > 0))
- ) {
- throw new Check.DeveloperError(iso8601ErrorMessage);
- }
- //>>includeEnd('debug');
- //Check the UTC offset value, if no value exists, use local time
- //a Z indicates UTC, + or - are offsets.
- var offset = tokens[offsetIndex];
- var offsetHours = +tokens[offsetIndex + 1];
- var offsetMinutes = +(tokens[offsetIndex + 2] || 0);
- switch (offset) {
- case "+":
- hour = hour - offsetHours;
- minute = minute - offsetMinutes;
- break;
- case "-":
- hour = hour + offsetHours;
- minute = minute + offsetMinutes;
- break;
- case "Z":
- break;
- default:
- minute =
- minute +
- new Date(
- Date.UTC(year, month - 1, day, hour, minute)
- ).getTimezoneOffset();
- break;
- }
- }
- //ISO8601 denotes a leap second by any time having a seconds component of 60 seconds.
- //If that's the case, we need to temporarily subtract a second in order to build a UTC date.
- //Then we add it back in after converting to TAI.
- var isLeapSecond = second === 60;
- if (isLeapSecond) {
- second--;
- }
- //Even if we successfully parsed the string into its components, after applying UTC offset or
- //special cases like 24:00:00 denoting midnight, we need to normalize the data appropriately.
- //milliseconds can never be greater than 1000, and seconds can't be above 60, so we start with minutes
- while (minute >= 60) {
- minute -= 60;
- hour++;
- }
- while (hour >= 24) {
- hour -= 24;
- day++;
- }
- tmp = inLeapYear && month === 2 ? daysInLeapFeburary : daysInMonth[month - 1];
- while (day > tmp) {
- day -= tmp;
- month++;
- if (month > 12) {
- month -= 12;
- year++;
- }
- tmp =
- inLeapYear && month === 2 ? daysInLeapFeburary : daysInMonth[month - 1];
- }
- //If UTC offset is at the beginning/end of the day, minutes can be negative.
- while (minute < 0) {
- minute += 60;
- hour--;
- }
- while (hour < 0) {
- hour += 24;
- day--;
- }
- while (day < 1) {
- month--;
- if (month < 1) {
- month += 12;
- year--;
- }
- tmp =
- inLeapYear && month === 2 ? daysInLeapFeburary : daysInMonth[month - 1];
- day += tmp;
- }
- //Now create the JulianDate components from the Gregorian date and actually create our instance.
- var components = computeJulianDateComponents(
- year,
- month,
- day,
- hour,
- minute,
- second,
- millisecond
- );
- if (!when.defined(result)) {
- result = new JulianDate(components[0], components[1], TimeStandard$1.UTC);
- } else {
- setComponents(components[0], components[1], result);
- convertUtcToTai(result);
- }
- //If we were on a leap second, add it back.
- if (isLeapSecond) {
- JulianDate.addSeconds(result, 1, result);
- }
- return result;
- };
- /**
- * Creates a new instance that represents the current system time.
- * This is equivalent to calling <code>JulianDate.fromDate(new Date());</code>.
- *
- * @param {JulianDate} [result] An existing instance to use for the result.
- * @returns {JulianDate} The modified result parameter or a new instance if none was provided.
- */
- JulianDate.now = function (result) {
- return JulianDate.fromDate(new Date(), result);
- };
- var toGregorianDateScratch = new JulianDate(0, 0, TimeStandard$1.TAI);
- /**
- * Creates a {@link GregorianDate} from the provided instance.
- *
- * @param {JulianDate} julianDate The date to be converted.
- * @param {GregorianDate} [result] An existing instance to use for the result.
- * @returns {GregorianDate} The modified result parameter or a new instance if none was provided.
- */
- JulianDate.toGregorianDate = function (julianDate, result) {
- //>>includeStart('debug', pragmas.debug);
- if (!when.defined(julianDate)) {
- throw new Check.DeveloperError("julianDate is required.");
- }
- //>>includeEnd('debug');
- var isLeapSecond = false;
- var thisUtc = convertTaiToUtc(julianDate, toGregorianDateScratch);
- if (!when.defined(thisUtc)) {
- //Conversion to UTC will fail if we are during a leap second.
- //If that's the case, subtract a second and convert again.
- //JavaScript doesn't support leap seconds, so this results in second 59 being repeated twice.
- JulianDate.addSeconds(julianDate, -1, toGregorianDateScratch);
- thisUtc = convertTaiToUtc(toGregorianDateScratch, toGregorianDateScratch);
- isLeapSecond = true;
- }
- var julianDayNumber = thisUtc.dayNumber;
- var secondsOfDay = thisUtc.secondsOfDay;
- if (secondsOfDay >= 43200.0) {
- julianDayNumber += 1;
- }
- // Algorithm from page 604 of the Explanatory Supplement to the
- // Astronomical Almanac (Seidelmann 1992).
- var L = (julianDayNumber + 68569) | 0;
- var N = ((4 * L) / 146097) | 0;
- L = (L - (((146097 * N + 3) / 4) | 0)) | 0;
- var I = ((4000 * (L + 1)) / 1461001) | 0;
- L = (L - (((1461 * I) / 4) | 0) + 31) | 0;
- var J = ((80 * L) / 2447) | 0;
- var day = (L - (((2447 * J) / 80) | 0)) | 0;
- L = (J / 11) | 0;
- var month = (J + 2 - 12 * L) | 0;
- var year = (100 * (N - 49) + I + L) | 0;
- var hour = (secondsOfDay / TimeConstants$1.SECONDS_PER_HOUR) | 0;
- var remainingSeconds = secondsOfDay - hour * TimeConstants$1.SECONDS_PER_HOUR;
- var minute = (remainingSeconds / TimeConstants$1.SECONDS_PER_MINUTE) | 0;
- remainingSeconds =
- remainingSeconds - minute * TimeConstants$1.SECONDS_PER_MINUTE;
- var second = remainingSeconds | 0;
- var millisecond =
- (remainingSeconds - second) / TimeConstants$1.SECONDS_PER_MILLISECOND;
- // JulianDates are noon-based
- hour += 12;
- if (hour > 23) {
- hour -= 24;
- }
- //If we were on a leap second, add it back.
- if (isLeapSecond) {
- second += 1;
- }
- if (!when.defined(result)) {
- return new GregorianDate(
- year,
- month,
- day,
- hour,
- minute,
- second,
- millisecond,
- isLeapSecond
- );
- }
- result.year = year;
- result.month = month;
- result.day = day;
- result.hour = hour;
- result.minute = minute;
- result.second = second;
- result.millisecond = millisecond;
- result.isLeapSecond = isLeapSecond;
- return result;
- };
- /**
- * Creates a JavaScript Date from the provided instance.
- * Since JavaScript dates are only accurate to the nearest millisecond and
- * cannot represent a leap second, consider using {@link JulianDate.toGregorianDate} instead.
- * If the provided JulianDate is during a leap second, the previous second is used.
- *
- * @param {JulianDate} julianDate The date to be converted.
- * @returns {Date} A new instance representing the provided date.
- */
- JulianDate.toDate = function (julianDate) {
- //>>includeStart('debug', pragmas.debug);
- if (!when.defined(julianDate)) {
- throw new Check.DeveloperError("julianDate is required.");
- }
- //>>includeEnd('debug');
- var gDate = JulianDate.toGregorianDate(julianDate, gregorianDateScratch);
- var second = gDate.second;
- if (gDate.isLeapSecond) {
- second -= 1;
- }
- return new Date(
- Date.UTC(
- gDate.year,
- gDate.month - 1,
- gDate.day,
- gDate.hour,
- gDate.minute,
- second,
- gDate.millisecond
- )
- );
- };
- /**
- * Creates an ISO8601 representation of the provided date.
- *
- * @param {JulianDate} julianDate The date to be converted.
- * @param {Number} [precision] The number of fractional digits used to represent the seconds component. By default, the most precise representation is used.
- * @returns {String} The ISO8601 representation of the provided date.
- */
- JulianDate.toIso8601 = function (julianDate, precision) {
- //>>includeStart('debug', pragmas.debug);
- if (!when.defined(julianDate)) {
- throw new Check.DeveloperError("julianDate is required.");
- }
- //>>includeEnd('debug');
- var gDate = JulianDate.toGregorianDate(julianDate, gregorianDateScratch);
- var year = gDate.year;
- var month = gDate.month;
- var day = gDate.day;
- var hour = gDate.hour;
- var minute = gDate.minute;
- var second = gDate.second;
- var millisecond = gDate.millisecond;
- // special case - Iso8601.MAXIMUM_VALUE produces a string which we can't parse unless we adjust.
- // 10000-01-01T00:00:00 is the same instant as 9999-12-31T24:00:00
- if (
- year === 10000 &&
- month === 1 &&
- day === 1 &&
- hour === 0 &&
- minute === 0 &&
- second === 0 &&
- millisecond === 0
- ) {
- year = 9999;
- month = 12;
- day = 31;
- hour = 24;
- }
- var millisecondStr;
- if (!when.defined(precision) && millisecond !== 0) {
- //Forces milliseconds into a number with at least 3 digits to whatever the default toString() precision is.
- millisecondStr = (millisecond * 0.01).toString().replace(".", "");
- return sprintf(
- "%04d-%02d-%02dT%02d:%02d:%02d.%sZ",
- year,
- month,
- day,
- hour,
- minute,
- second,
- millisecondStr
- );
- }
- //Precision is either 0 or milliseconds is 0 with undefined precision, in either case, leave off milliseconds entirely
- if (!when.defined(precision) || precision === 0) {
- return sprintf(
- "%04d-%02d-%02dT%02d:%02d:%02dZ",
- year,
- month,
- day,
- hour,
- minute,
- second
- );
- }
- //Forces milliseconds into a number with at least 3 digits to whatever the specified precision is.
- millisecondStr = (millisecond * 0.01)
- .toFixed(precision)
- .replace(".", "")
- .slice(0, precision);
- return sprintf(
- "%04d-%02d-%02dT%02d:%02d:%02d.%sZ",
- year,
- month,
- day,
- hour,
- minute,
- second,
- millisecondStr
- );
- };
- /**
- * Duplicates a JulianDate instance.
- *
- * @param {JulianDate} julianDate The date to duplicate.
- * @param {JulianDate} [result] An existing instance to use for the result.
- * @returns {JulianDate} The modified result parameter or a new instance if none was provided. Returns undefined if julianDate is undefined.
- */
- JulianDate.clone = function (julianDate, result) {
- if (!when.defined(julianDate)) {
- return undefined;
- }
- if (!when.defined(result)) {
- return new JulianDate(
- julianDate.dayNumber,
- julianDate.secondsOfDay,
- TimeStandard$1.TAI
- );
- }
- result.dayNumber = julianDate.dayNumber;
- result.secondsOfDay = julianDate.secondsOfDay;
- return result;
- };
- /**
- * Compares two instances.
- *
- * @param {JulianDate} left The first instance.
- * @param {JulianDate} right The second instance.
- * @returns {Number} A negative value if left is less than right, a positive value if left is greater than right, or zero if left and right are equal.
- */
- JulianDate.compare = function (left, right) {
- //>>includeStart('debug', pragmas.debug);
- if (!when.defined(left)) {
- throw new Check.DeveloperError("left is required.");
- }
- if (!when.defined(right)) {
- throw new Check.DeveloperError("right is required.");
- }
- //>>includeEnd('debug');
- var julianDayNumberDifference = left.dayNumber - right.dayNumber;
- if (julianDayNumberDifference !== 0) {
- return julianDayNumberDifference;
- }
- return left.secondsOfDay - right.secondsOfDay;
- };
- /**
- * Compares two instances and returns <code>true</code> if they are equal, <code>false</code> otherwise.
- *
- * @param {JulianDate} [left] The first instance.
- * @param {JulianDate} [right] The second instance.
- * @returns {Boolean} <code>true</code> if the dates are equal; otherwise, <code>false</code>.
- */
- JulianDate.equals = function (left, right) {
- return (
- left === right ||
- (when.defined(left) &&
- when.defined(right) &&
- left.dayNumber === right.dayNumber &&
- left.secondsOfDay === right.secondsOfDay)
- );
- };
- /**
- * Compares two instances and returns <code>true</code> if they are within <code>epsilon</code> seconds of
- * each other. That is, in order for the dates to be considered equal (and for
- * this function to return <code>true</code>), the absolute value of the difference between them, in
- * seconds, must be less than <code>epsilon</code>.
- *
- * @param {JulianDate} [left] The first instance.
- * @param {JulianDate} [right] The second instance.
- * @param {Number} [epsilon=0] The maximum number of seconds that should separate the two instances.
- * @returns {Boolean} <code>true</code> if the two dates are within <code>epsilon</code> seconds of each other; otherwise <code>false</code>.
- */
- JulianDate.equalsEpsilon = function (left, right, epsilon) {
- epsilon = when.defaultValue(epsilon, 0);
- return (
- left === right ||
- (when.defined(left) &&
- when.defined(right) &&
- Math.abs(JulianDate.secondsDifference(left, right)) <= epsilon)
- );
- };
- /**
- * Computes the total number of whole and fractional days represented by the provided instance.
- *
- * @param {JulianDate} julianDate The date.
- * @returns {Number} The Julian date as single floating point number.
- */
- JulianDate.totalDays = function (julianDate) {
- //>>includeStart('debug', pragmas.debug);
- if (!when.defined(julianDate)) {
- throw new Check.DeveloperError("julianDate is required.");
- }
- //>>includeEnd('debug');
- return (
- julianDate.dayNumber +
- julianDate.secondsOfDay / TimeConstants$1.SECONDS_PER_DAY
- );
- };
- /**
- * Computes the difference in seconds between the provided instance.
- *
- * @param {JulianDate} left The first instance.
- * @param {JulianDate} right The second instance.
- * @returns {Number} The difference, in seconds, when subtracting <code>right</code> from <code>left</code>.
- */
- JulianDate.secondsDifference = function (left, right) {
- //>>includeStart('debug', pragmas.debug);
- if (!when.defined(left)) {
- throw new Check.DeveloperError("left is required.");
- }
- if (!when.defined(right)) {
- throw new Check.DeveloperError("right is required.");
- }
- //>>includeEnd('debug');
- var dayDifference =
- (left.dayNumber - right.dayNumber) * TimeConstants$1.SECONDS_PER_DAY;
- return dayDifference + (left.secondsOfDay - right.secondsOfDay);
- };
- /**
- * Computes the difference in days between the provided instance.
- *
- * @param {JulianDate} left The first instance.
- * @param {JulianDate} right The second instance.
- * @returns {Number} The difference, in days, when subtracting <code>right</code> from <code>left</code>.
- */
- JulianDate.daysDifference = function (left, right) {
- //>>includeStart('debug', pragmas.debug);
- if (!when.defined(left)) {
- throw new Check.DeveloperError("left is required.");
- }
- if (!when.defined(right)) {
- throw new Check.DeveloperError("right is required.");
- }
- //>>includeEnd('debug');
- var dayDifference = left.dayNumber - right.dayNumber;
- var secondDifference =
- (left.secondsOfDay - right.secondsOfDay) / TimeConstants$1.SECONDS_PER_DAY;
- return dayDifference + secondDifference;
- };
- /**
- * Computes the number of seconds the provided instance is ahead of UTC.
- *
- * @param {JulianDate} julianDate The date.
- * @returns {Number} The number of seconds the provided instance is ahead of UTC
- */
- JulianDate.computeTaiMinusUtc = function (julianDate) {
- binarySearchScratchLeapSecond.julianDate = julianDate;
- var leapSeconds = JulianDate.leapSeconds;
- var index = binarySearch(
- leapSeconds,
- binarySearchScratchLeapSecond,
- compareLeapSecondDates
- );
- if (index < 0) {
- index = ~index;
- --index;
- if (index < 0) {
- index = 0;
- }
- }
- return leapSeconds[index].offset;
- };
- /**
- * Adds the provided number of seconds to the provided date instance.
- *
- * @param {JulianDate} julianDate The date.
- * @param {Number} seconds The number of seconds to add or subtract.
- * @param {JulianDate} result An existing instance to use for the result.
- * @returns {JulianDate} The modified result parameter.
- */
- JulianDate.addSeconds = function (julianDate, seconds, result) {
- //>>includeStart('debug', pragmas.debug);
- if (!when.defined(julianDate)) {
- throw new Check.DeveloperError("julianDate is required.");
- }
- if (!when.defined(seconds)) {
- throw new Check.DeveloperError("seconds is required.");
- }
- if (!when.defined(result)) {
- throw new Check.DeveloperError("result is required.");
- }
- //>>includeEnd('debug');
- return setComponents(
- julianDate.dayNumber,
- julianDate.secondsOfDay + seconds,
- result
- );
- };
- /**
- * Adds the provided number of minutes to the provided date instance.
- *
- * @param {JulianDate} julianDate The date.
- * @param {Number} minutes The number of minutes to add or subtract.
- * @param {JulianDate} result An existing instance to use for the result.
- * @returns {JulianDate} The modified result parameter.
- */
- JulianDate.addMinutes = function (julianDate, minutes, result) {
- //>>includeStart('debug', pragmas.debug);
- if (!when.defined(julianDate)) {
- throw new Check.DeveloperError("julianDate is required.");
- }
- if (!when.defined(minutes)) {
- throw new Check.DeveloperError("minutes is required.");
- }
- if (!when.defined(result)) {
- throw new Check.DeveloperError("result is required.");
- }
- //>>includeEnd('debug');
- var newSecondsOfDay =
- julianDate.secondsOfDay + minutes * TimeConstants$1.SECONDS_PER_MINUTE;
- return setComponents(julianDate.dayNumber, newSecondsOfDay, result);
- };
- /**
- * Adds the provided number of hours to the provided date instance.
- *
- * @param {JulianDate} julianDate The date.
- * @param {Number} hours The number of hours to add or subtract.
- * @param {JulianDate} result An existing instance to use for the result.
- * @returns {JulianDate} The modified result parameter.
- */
- JulianDate.addHours = function (julianDate, hours, result) {
- //>>includeStart('debug', pragmas.debug);
- if (!when.defined(julianDate)) {
- throw new Check.DeveloperError("julianDate is required.");
- }
- if (!when.defined(hours)) {
- throw new Check.DeveloperError("hours is required.");
- }
- if (!when.defined(result)) {
- throw new Check.DeveloperError("result is required.");
- }
- //>>includeEnd('debug');
- var newSecondsOfDay =
- julianDate.secondsOfDay + hours * TimeConstants$1.SECONDS_PER_HOUR;
- return setComponents(julianDate.dayNumber, newSecondsOfDay, result);
- };
- /**
- * Adds the provided number of days to the provided date instance.
- *
- * @param {JulianDate} julianDate The date.
- * @param {Number} days The number of days to add or subtract.
- * @param {JulianDate} result An existing instance to use for the result.
- * @returns {JulianDate} The modified result parameter.
- */
- JulianDate.addDays = function (julianDate, days, result) {
- //>>includeStart('debug', pragmas.debug);
- if (!when.defined(julianDate)) {
- throw new Check.DeveloperError("julianDate is required.");
- }
- if (!when.defined(days)) {
- throw new Check.DeveloperError("days is required.");
- }
- if (!when.defined(result)) {
- throw new Check.DeveloperError("result is required.");
- }
- //>>includeEnd('debug');
- var newJulianDayNumber = julianDate.dayNumber + days;
- return setComponents(newJulianDayNumber, julianDate.secondsOfDay, result);
- };
- /**
- * Compares the provided instances and returns <code>true</code> if <code>left</code> is earlier than <code>right</code>, <code>false</code> otherwise.
- *
- * @param {JulianDate} left The first instance.
- * @param {JulianDate} right The second instance.
- * @returns {Boolean} <code>true</code> if <code>left</code> is earlier than <code>right</code>, <code>false</code> otherwise.
- */
- JulianDate.lessThan = function (left, right) {
- return JulianDate.compare(left, right) < 0;
- };
- /**
- * Compares the provided instances and returns <code>true</code> if <code>left</code> is earlier than or equal to <code>right</code>, <code>false</code> otherwise.
- *
- * @param {JulianDate} left The first instance.
- * @param {JulianDate} right The second instance.
- * @returns {Boolean} <code>true</code> if <code>left</code> is earlier than or equal to <code>right</code>, <code>false</code> otherwise.
- */
- JulianDate.lessThanOrEquals = function (left, right) {
- return JulianDate.compare(left, right) <= 0;
- };
- /**
- * Compares the provided instances and returns <code>true</code> if <code>left</code> is later than <code>right</code>, <code>false</code> otherwise.
- *
- * @param {JulianDate} left The first instance.
- * @param {JulianDate} right The second instance.
- * @returns {Boolean} <code>true</code> if <code>left</code> is later than <code>right</code>, <code>false</code> otherwise.
- */
- JulianDate.greaterThan = function (left, right) {
- return JulianDate.compare(left, right) > 0;
- };
- /**
- * Compares the provided instances and returns <code>true</code> if <code>left</code> is later than or equal to <code>right</code>, <code>false</code> otherwise.
- *
- * @param {JulianDate} left The first instance.
- * @param {JulianDate} right The second instance.
- * @returns {Boolean} <code>true</code> if <code>left</code> is later than or equal to <code>right</code>, <code>false</code> otherwise.
- */
- JulianDate.greaterThanOrEquals = function (left, right) {
- return JulianDate.compare(left, right) >= 0;
- };
- /**
- * Duplicates this instance.
- *
- * @param {JulianDate} [result] An existing instance to use for the result.
- * @returns {JulianDate} The modified result parameter or a new instance if none was provided.
- */
- JulianDate.prototype.clone = function (result) {
- return JulianDate.clone(this, result);
- };
- /**
- * Compares this and the provided instance and returns <code>true</code> if they are equal, <code>false</code> otherwise.
- *
- * @param {JulianDate} [right] The second instance.
- * @returns {Boolean} <code>true</code> if the dates are equal; otherwise, <code>false</code>.
- */
- JulianDate.prototype.equals = function (right) {
- return JulianDate.equals(this, right);
- };
- /**
- * Compares this and the provided instance and returns <code>true</code> if they are within <code>epsilon</code> seconds of
- * each other. That is, in order for the dates to be considered equal (and for
- * this function to return <code>true</code>), the absolute value of the difference between them, in
- * seconds, must be less than <code>epsilon</code>.
- *
- * @param {JulianDate} [right] The second instance.
- * @param {Number} [epsilon=0] The maximum number of seconds that should separate the two instances.
- * @returns {Boolean} <code>true</code> if the two dates are within <code>epsilon</code> seconds of each other; otherwise <code>false</code>.
- */
- JulianDate.prototype.equalsEpsilon = function (right, epsilon) {
- return JulianDate.equalsEpsilon(this, right, epsilon);
- };
- /**
- * Creates a string representing this date in ISO8601 format.
- *
- * @returns {String} A string representing this date in ISO8601 format.
- */
- JulianDate.prototype.toString = function () {
- return JulianDate.toIso8601(this);
- };
- /**
- * Gets or sets the list of leap seconds used throughout Cesium.
- * @memberof JulianDate
- * @type {LeapSecond[]}
- */
- JulianDate.leapSeconds = [
- new LeapSecond(new JulianDate(2441317, 43210.0, TimeStandard$1.TAI), 10), // January 1, 1972 00:00:00 UTC
- new LeapSecond(new JulianDate(2441499, 43211.0, TimeStandard$1.TAI), 11), // July 1, 1972 00:00:00 UTC
- new LeapSecond(new JulianDate(2441683, 43212.0, TimeStandard$1.TAI), 12), // January 1, 1973 00:00:00 UTC
- new LeapSecond(new JulianDate(2442048, 43213.0, TimeStandard$1.TAI), 13), // January 1, 1974 00:00:00 UTC
- new LeapSecond(new JulianDate(2442413, 43214.0, TimeStandard$1.TAI), 14), // January 1, 1975 00:00:00 UTC
- new LeapSecond(new JulianDate(2442778, 43215.0, TimeStandard$1.TAI), 15), // January 1, 1976 00:00:00 UTC
- new LeapSecond(new JulianDate(2443144, 43216.0, TimeStandard$1.TAI), 16), // January 1, 1977 00:00:00 UTC
- new LeapSecond(new JulianDate(2443509, 43217.0, TimeStandard$1.TAI), 17), // January 1, 1978 00:00:00 UTC
- new LeapSecond(new JulianDate(2443874, 43218.0, TimeStandard$1.TAI), 18), // January 1, 1979 00:00:00 UTC
- new LeapSecond(new JulianDate(2444239, 43219.0, TimeStandard$1.TAI), 19), // January 1, 1980 00:00:00 UTC
- new LeapSecond(new JulianDate(2444786, 43220.0, TimeStandard$1.TAI), 20), // July 1, 1981 00:00:00 UTC
- new LeapSecond(new JulianDate(2445151, 43221.0, TimeStandard$1.TAI), 21), // July 1, 1982 00:00:00 UTC
- new LeapSecond(new JulianDate(2445516, 43222.0, TimeStandard$1.TAI), 22), // July 1, 1983 00:00:00 UTC
- new LeapSecond(new JulianDate(2446247, 43223.0, TimeStandard$1.TAI), 23), // July 1, 1985 00:00:00 UTC
- new LeapSecond(new JulianDate(2447161, 43224.0, TimeStandard$1.TAI), 24), // January 1, 1988 00:00:00 UTC
- new LeapSecond(new JulianDate(2447892, 43225.0, TimeStandard$1.TAI), 25), // January 1, 1990 00:00:00 UTC
- new LeapSecond(new JulianDate(2448257, 43226.0, TimeStandard$1.TAI), 26), // January 1, 1991 00:00:00 UTC
- new LeapSecond(new JulianDate(2448804, 43227.0, TimeStandard$1.TAI), 27), // July 1, 1992 00:00:00 UTC
- new LeapSecond(new JulianDate(2449169, 43228.0, TimeStandard$1.TAI), 28), // July 1, 1993 00:00:00 UTC
- new LeapSecond(new JulianDate(2449534, 43229.0, TimeStandard$1.TAI), 29), // July 1, 1994 00:00:00 UTC
- new LeapSecond(new JulianDate(2450083, 43230.0, TimeStandard$1.TAI), 30), // January 1, 1996 00:00:00 UTC
- new LeapSecond(new JulianDate(2450630, 43231.0, TimeStandard$1.TAI), 31), // July 1, 1997 00:00:00 UTC
- new LeapSecond(new JulianDate(2451179, 43232.0, TimeStandard$1.TAI), 32), // January 1, 1999 00:00:00 UTC
- new LeapSecond(new JulianDate(2453736, 43233.0, TimeStandard$1.TAI), 33), // January 1, 2006 00:00:00 UTC
- new LeapSecond(new JulianDate(2454832, 43234.0, TimeStandard$1.TAI), 34), // January 1, 2009 00:00:00 UTC
- new LeapSecond(new JulianDate(2456109, 43235.0, TimeStandard$1.TAI), 35), // July 1, 2012 00:00:00 UTC
- new LeapSecond(new JulianDate(2457204, 43236.0, TimeStandard$1.TAI), 36), // July 1, 2015 00:00:00 UTC
- new LeapSecond(new JulianDate(2457754, 43237.0, TimeStandard$1.TAI), 37), // January 1, 2017 00:00:00 UTC
- ];
- /**
- * @license
- *
- * Grauw URI utilities
- *
- * See: http://hg.grauw.nl/grauw-lib/file/tip/src/uri.js
- *
- * @author Laurens Holst (http://www.grauw.nl/)
- *
- * Copyright 2012 Laurens Holst
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
- /**
- * Constructs a URI object.
- * @constructor
- * @class Implementation of URI parsing and base URI resolving algorithm in RFC 3986.
- * @param {string|URI} uri A string or URI object to create the object from.
- */
- function URI(uri) {
- if (uri instanceof URI) { // copy constructor
- this.scheme = uri.scheme;
- this.authority = uri.authority;
- this.path = uri.path;
- this.query = uri.query;
- this.fragment = uri.fragment;
- } else if (uri) { // uri is URI string or cast to string
- var c = parseRegex.exec(uri);
- this.scheme = c[1];
- this.authority = c[2];
- this.path = c[3];
- this.query = c[4];
- this.fragment = c[5];
- }
- }
- // Initial values on the prototype
- URI.prototype.scheme = null;
- URI.prototype.authority = null;
- URI.prototype.path = '';
- URI.prototype.query = null;
- URI.prototype.fragment = null;
- // Regular expression from RFC 3986 appendix B
- var parseRegex = new RegExp('^(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\\?([^#]*))?(?:#(.*))?$');
- /**
- * Returns the scheme part of the URI.
- * In "http://example.com:80/a/b?x#y" this is "http".
- */
- URI.prototype.getScheme = function() {
- return this.scheme;
- };
- /**
- * Returns the authority part of the URI.
- * In "http://example.com:80/a/b?x#y" this is "example.com:80".
- */
- URI.prototype.getAuthority = function() {
- return this.authority;
- };
- /**
- * Returns the path part of the URI.
- * In "http://example.com:80/a/b?x#y" this is "/a/b".
- * In "mailto:mike@example.com" this is "mike@example.com".
- */
- URI.prototype.getPath = function() {
- return this.path;
- };
- /**
- * Returns the query part of the URI.
- * In "http://example.com:80/a/b?x#y" this is "x".
- */
- URI.prototype.getQuery = function() {
- return this.query;
- };
- /**
- * Returns the fragment part of the URI.
- * In "http://example.com:80/a/b?x#y" this is "y".
- */
- URI.prototype.getFragment = function() {
- return this.fragment;
- };
- /**
- * Tests whether the URI is an absolute URI.
- * See RFC 3986 section 4.3.
- */
- URI.prototype.isAbsolute = function() {
- return !!this.scheme && !this.fragment;
- };
- ///**
- //* Extensive validation of the URI against the ABNF in RFC 3986
- //*/
- //URI.prototype.validate
- /**
- * Tests whether the URI is a same-document reference.
- * See RFC 3986 section 4.4.
- *
- * To perform more thorough comparison, you can normalise the URI objects.
- */
- URI.prototype.isSameDocumentAs = function(uri) {
- return uri.scheme == this.scheme &&
- uri.authority == this.authority &&
- uri.path == this.path &&
- uri.query == this.query;
- };
- /**
- * Simple String Comparison of two URIs.
- * See RFC 3986 section 6.2.1.
- *
- * To perform more thorough comparison, you can normalise the URI objects.
- */
- URI.prototype.equals = function(uri) {
- return this.isSameDocumentAs(uri) && uri.fragment == this.fragment;
- };
- /**
- * Normalizes the URI using syntax-based normalization.
- * This includes case normalization, percent-encoding normalization and path segment normalization.
- * XXX: Percent-encoding normalization does not escape characters that need to be escaped.
- * (Although that would not be a valid URI in the first place. See validate().)
- * See RFC 3986 section 6.2.2.
- */
- URI.prototype.normalize = function() {
- this.removeDotSegments();
- if (this.scheme)
- this.scheme = this.scheme.toLowerCase();
- if (this.authority)
- this.authority = this.authority.replace(authorityRegex, replaceAuthority).
- replace(caseRegex, replaceCase);
- if (this.path)
- this.path = this.path.replace(caseRegex, replaceCase);
- if (this.query)
- this.query = this.query.replace(caseRegex, replaceCase);
- if (this.fragment)
- this.fragment = this.fragment.replace(caseRegex, replaceCase);
- };
- var caseRegex = /%[0-9a-z]{2}/gi;
- var percentRegex = /[a-zA-Z0-9\-\._~]/;
- var authorityRegex = /(.*@)?([^@:]*)(:.*)?/;
- function replaceCase(str) {
- var dec = unescape(str);
- return percentRegex.test(dec) ? dec : str.toUpperCase();
- }
- function replaceAuthority(str, p1, p2, p3) {
- return (p1 || '') + p2.toLowerCase() + (p3 || '');
- }
- /**
- * Resolve a relative URI (this) against a base URI.
- * The base URI must be an absolute URI.
- * See RFC 3986 section 5.2
- */
- URI.prototype.resolve = function(baseURI) {
- var uri = new URI();
- if (this.scheme) {
- uri.scheme = this.scheme;
- uri.authority = this.authority;
- uri.path = this.path;
- uri.query = this.query;
- } else {
- uri.scheme = baseURI.scheme;
- if (this.authority) {
- uri.authority = this.authority;
- uri.path = this.path;
- uri.query = this.query;
- } else {
- uri.authority = baseURI.authority;
- if (this.path == '') {
- uri.path = baseURI.path;
- uri.query = this.query || baseURI.query;
- } else {
- if (this.path.charAt(0) == '/') {
- uri.path = this.path;
- uri.removeDotSegments();
- } else {
- if (baseURI.authority && baseURI.path == '') {
- uri.path = '/' + this.path;
- } else {
- uri.path = baseURI.path.substring(0, baseURI.path.lastIndexOf('/') + 1) + this.path;
- }
- uri.removeDotSegments();
- }
- uri.query = this.query;
- }
- }
- }
- uri.fragment = this.fragment;
- return uri;
- };
- /**
- * Remove dot segments from path.
- * See RFC 3986 section 5.2.4
- * @private
- */
- URI.prototype.removeDotSegments = function() {
- var input = this.path.split('/'),
- output = [],
- segment,
- absPath = input[0] == '';
- if (absPath)
- input.shift();
- var sFirst = input[0] == '' ? input.shift() : null;
- while (input.length) {
- segment = input.shift();
- if (segment == '..') {
- output.pop();
- } else if (segment != '.') {
- output.push(segment);
- }
- }
- if (segment == '.' || segment == '..')
- output.push('');
- if (absPath)
- output.unshift('');
- this.path = output.join('/');
- };
- // We don't like this function because it builds up a cache that is never cleared.
- // /**
- // * Resolves a relative URI against an absolute base URI.
- // * Convenience method.
- // * @param {String} uri the relative URI to resolve
- // * @param {String} baseURI the base URI (must be absolute) to resolve against
- // */
- // URI.resolve = function(sURI, sBaseURI) {
- // var uri = cache[sURI] || (cache[sURI] = new URI(sURI));
- // var baseURI = cache[sBaseURI] || (cache[sBaseURI] = new URI(sBaseURI));
- // return uri.resolve(baseURI).toString();
- // };
- // var cache = {};
- /**
- * Serialises the URI to a string.
- */
- URI.prototype.toString = function() {
- var result = '';
- if (this.scheme)
- result += this.scheme + ':';
- if (this.authority)
- result += '//' + this.authority;
- result += this.path;
- if (this.query)
- result += '?' + this.query;
- if (this.fragment)
- result += '#' + this.fragment;
- return result;
- };
- /**
- * @private
- */
- function appendForwardSlash(url) {
- if (url.length === 0 || url[url.length - 1] !== "/") {
- url = url + "/";
- }
- return url;
- }
- /**
- * Clones an object, returning a new object containing the same properties.
- *
- * @function
- *
- * @param {Object} object The object to clone.
- * @param {Boolean} [deep=false] If true, all properties will be deep cloned recursively.
- * @returns {Object} The cloned object.
- */
- function clone(object, deep) {
- if (object === null || typeof object !== "object") {
- return object;
- }
- deep = when.defaultValue(deep, false);
- var result = new object.constructor();
- for (var propertyName in object) {
- if (object.hasOwnProperty(propertyName)) {
- var value = object[propertyName];
- if (deep) {
- value = clone(value, deep);
- }
- result[propertyName] = value;
- }
- }
- return result;
- }
- /**
- * Merges two objects, copying their properties onto a new combined object. When two objects have the same
- * property, the value of the property on the first object is used. If either object is undefined,
- * it will be treated as an empty object.
- *
- * @example
- * var object1 = {
- * propOne : 1,
- * propTwo : {
- * value1 : 10
- * }
- * }
- * var object2 = {
- * propTwo : 2
- * }
- * var final = Cesium.combine(object1, object2);
- *
- * // final === {
- * // propOne : 1,
- * // propTwo : {
- * // value1 : 10
- * // }
- * // }
- *
- * @param {Object} [object1] The first object to merge.
- * @param {Object} [object2] The second object to merge.
- * @param {Boolean} [deep=false] Perform a recursive merge.
- * @returns {Object} The combined object containing all properties from both objects.
- *
- * @function
- */
- function combine(object1, object2, deep) {
- deep = when.defaultValue(deep, false);
- var result = {};
- var object1Defined = when.defined(object1);
- var object2Defined = when.defined(object2);
- var property;
- var object1Value;
- var object2Value;
- if (object1Defined) {
- for (property in object1) {
- if (object1.hasOwnProperty(property)) {
- object1Value = object1[property];
- if (
- object2Defined &&
- deep &&
- typeof object1Value === "object" &&
- object2.hasOwnProperty(property)
- ) {
- object2Value = object2[property];
- if (typeof object2Value === "object") {
- result[property] = combine(object1Value, object2Value, deep);
- } else {
- result[property] = object1Value;
- }
- } else {
- result[property] = object1Value;
- }
- }
- }
- }
- if (object2Defined) {
- for (property in object2) {
- if (
- object2.hasOwnProperty(property) &&
- !result.hasOwnProperty(property)
- ) {
- object2Value = object2[property];
- result[property] = object2Value;
- }
- }
- }
- return result;
- }
- /**
- * Given a relative Uri and a base Uri, returns the absolute Uri of the relative Uri.
- * @function
- *
- * @param {String} relative The relative Uri.
- * @param {String} [base] The base Uri.
- * @returns {String} The absolute Uri of the given relative Uri.
- *
- * @example
- * //absolute Uri will be "https://test.com/awesome.png";
- * var absoluteUri = Cesium.getAbsoluteUri('awesome.png', 'https://test.com');
- */
- function getAbsoluteUri(relative, base) {
- var documentObject;
- if (typeof document !== "undefined") {
- documentObject = document;
- }
- return getAbsoluteUri._implementation(relative, base, documentObject);
- }
- getAbsoluteUri._implementation = function (relative, base, documentObject) {
- //>>includeStart('debug', pragmas.debug);
- if (!when.defined(relative)) {
- throw new Check.DeveloperError("relative uri is required.");
- }
- //>>includeEnd('debug');
- if (!when.defined(base)) {
- if (typeof documentObject === "undefined") {
- return relative;
- }
- base = when.defaultValue(documentObject.baseURI, documentObject.location.href);
- }
- var baseUri = new URI(base);
- var relativeUri = new URI(relative);
- return relativeUri.resolve(baseUri).toString();
- };
- /**
- * Given a URI, returns the base path of the URI.
- * @function
- *
- * @param {String} uri The Uri.
- * @param {Boolean} [includeQuery = false] Whether or not to include the query string and fragment form the uri
- * @returns {String} The base path of the Uri.
- *
- * @example
- * // basePath will be "/Gallery/";
- * var basePath = Cesium.getBaseUri('/Gallery/simple.czml?value=true&example=false');
- *
- * // basePath will be "/Gallery/?value=true&example=false";
- * var basePath = Cesium.getBaseUri('/Gallery/simple.czml?value=true&example=false', true);
- */
- function getBaseUri(uri, includeQuery) {
- //>>includeStart('debug', pragmas.debug);
- if (!when.defined(uri)) {
- throw new Check.DeveloperError("uri is required.");
- }
- //>>includeEnd('debug');
- var basePath = "";
- var i = uri.lastIndexOf("/");
- if (i !== -1) {
- basePath = uri.substring(0, i + 1);
- }
- if (!includeQuery) {
- return basePath;
- }
- uri = new URI(uri);
- if (when.defined(uri.query)) {
- basePath += "?" + uri.query;
- }
- if (when.defined(uri.fragment)) {
- basePath += "#" + uri.fragment;
- }
- return basePath;
- }
- /**
- * Given a URI, returns the extension of the URI.
- * @function getExtensionFromUri
- *
- * @param {String} uri The Uri.
- * @returns {String} The extension of the Uri.
- *
- * @example
- * //extension will be "czml";
- * var extension = Cesium.getExtensionFromUri('/Gallery/simple.czml?value=true&example=false');
- */
- function getExtensionFromUri(uri) {
- //>>includeStart('debug', pragmas.debug);
- if (!when.defined(uri)) {
- throw new Check.DeveloperError("uri is required.");
- }
- //>>includeEnd('debug');
- var uriObject = new URI(uri);
- uriObject.normalize();
- var path = uriObject.path;
- var index = path.lastIndexOf("/");
- if (index !== -1) {
- path = path.substr(index + 1);
- }
- index = path.lastIndexOf(".");
- if (index === -1) {
- path = "";
- } else {
- path = path.substr(index + 1);
- }
- return path;
- }
- var blobUriRegex = /^blob:/i;
- /**
- * Determines if the specified uri is a blob uri.
- *
- * @function isBlobUri
- *
- * @param {String} uri The uri to test.
- * @returns {Boolean} true when the uri is a blob uri; otherwise, false.
- *
- * @private
- */
- function isBlobUri(uri) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.string("uri", uri);
- //>>includeEnd('debug');
- return blobUriRegex.test(uri);
- }
- var a;
- /**
- * Given a URL, determine whether that URL is considered cross-origin to the current page.
- *
- * @private
- */
- function isCrossOriginUrl(url) {
- if (!when.defined(a)) {
- a = document.createElement("a");
- }
- // copy window location into the anchor to get consistent results
- // when the port is default for the protocol (e.g. 80 for HTTP)
- a.href = window.location.href;
- // host includes both hostname and port if the port is not standard
- var host = a.host;
- var protocol = a.protocol;
- a.href = url;
- // IE only absolutizes href on get, not set
- // eslint-disable-next-line no-self-assign
- a.href = a.href;
- return protocol !== a.protocol || host !== a.host;
- }
- var dataUriRegex = /^data:/i;
- /**
- * Determines if the specified uri is a data uri.
- *
- * @function isDataUri
- *
- * @param {String} uri The uri to test.
- * @returns {Boolean} true when the uri is a data uri; otherwise, false.
- *
- * @private
- */
- function isDataUri(uri) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.string("uri", uri);
- //>>includeEnd('debug');
- return dataUriRegex.test(uri);
- }
- /**
- * @private
- */
- function loadAndExecuteScript(url) {
- var deferred = when.when.defer();
- var script = document.createElement("script");
- script.async = true;
- script.src = url;
- var head = document.getElementsByTagName("head")[0];
- script.onload = function () {
- script.onload = undefined;
- head.removeChild(script);
- deferred.resolve();
- };
- script.onerror = function (e) {
- deferred.reject(e);
- };
- head.appendChild(script);
- return deferred.promise;
- }
- /**
- * Converts an object representing a set of name/value pairs into a query string,
- * with names and values encoded properly for use in a URL. Values that are arrays
- * will produce multiple values with the same name.
- * @function objectToQuery
- *
- * @param {Object} obj The object containing data to encode.
- * @returns {String} An encoded query string.
- *
- *
- * @example
- * var str = Cesium.objectToQuery({
- * key1 : 'some value',
- * key2 : 'a/b',
- * key3 : ['x', 'y']
- * });
- *
- * @see queryToObject
- * // str will be:
- * // 'key1=some%20value&key2=a%2Fb&key3=x&key3=y'
- */
- function objectToQuery(obj) {
- //>>includeStart('debug', pragmas.debug);
- if (!when.defined(obj)) {
- throw new Check.DeveloperError("obj is required.");
- }
- //>>includeEnd('debug');
- var result = "";
- for (var propName in obj) {
- if (obj.hasOwnProperty(propName)) {
- var value = obj[propName];
- var part = encodeURIComponent(propName) + "=";
- if (Array.isArray(value)) {
- for (var i = 0, len = value.length; i < len; ++i) {
- result += part + encodeURIComponent(value[i]) + "&";
- }
- } else {
- result += part + encodeURIComponent(value) + "&";
- }
- }
- }
- // trim last &
- result = result.slice(0, -1);
- // This function used to replace %20 with + which is more compact and readable.
- // However, some servers didn't properly handle + as a space.
- // https://github.com/CesiumGS/cesium/issues/2192
- return result;
- }
- /**
- * Parses a query string into an object, where the keys and values of the object are the
- * name/value pairs from the query string, decoded. If a name appears multiple times,
- * the value in the object will be an array of values.
- * @function queryToObject
- *
- * @param {String} queryString The query string.
- * @returns {Object} An object containing the parameters parsed from the query string.
- *
- *
- * @example
- * var obj = Cesium.queryToObject('key1=some%20value&key2=a%2Fb&key3=x&key3=y');
- * // obj will be:
- * // {
- * // key1 : 'some value',
- * // key2 : 'a/b',
- * // key3 : ['x', 'y']
- * // }
- *
- * @see objectToQuery
- */
- function queryToObject(queryString) {
- //>>includeStart('debug', pragmas.debug);
- if (!when.defined(queryString)) {
- throw new Check.DeveloperError("queryString is required.");
- }
- //>>includeEnd('debug');
- var result = {};
- if (queryString === "") {
- return result;
- }
- var parts = queryString.replace(/\+/g, "%20").split(/[&;]/);
- for (var i = 0, len = parts.length; i < len; ++i) {
- var subparts = parts[i].split("=");
- var name = decodeURIComponent(subparts[0]);
- var value = subparts[1];
- if (when.defined(value)) {
- value = decodeURIComponent(value);
- } else {
- value = "";
- }
- var resultValue = result[name];
- if (typeof resultValue === "string") {
- // expand the single value to an array
- result[name] = [resultValue, value];
- } else if (Array.isArray(resultValue)) {
- resultValue.push(value);
- } else {
- result[name] = value;
- }
- }
- return result;
- }
- /**
- * State of the request.
- *
- * @enum {Number}
- */
- var RequestState = {
- /**
- * Initial unissued state.
- *
- * @type Number
- * @constant
- */
- UNISSUED: 0,
- /**
- * Issued but not yet active. Will become active when open slots are available.
- *
- * @type Number
- * @constant
- */
- ISSUED: 1,
- /**
- * Actual http request has been sent.
- *
- * @type Number
- * @constant
- */
- ACTIVE: 2,
- /**
- * Request completed successfully.
- *
- * @type Number
- * @constant
- */
- RECEIVED: 3,
- /**
- * Request was cancelled, either explicitly or automatically because of low priority.
- *
- * @type Number
- * @constant
- */
- CANCELLED: 4,
- /**
- * Request failed.
- *
- * @type Number
- * @constant
- */
- FAILED: 5,
- };
- var RequestState$1 = Object.freeze(RequestState);
- /**
- * An enum identifying the type of request. Used for finer grained logging and priority sorting.
- *
- * @enum {Number}
- */
- var RequestType = {
- /**
- * Terrain request.
- *
- * @type Number
- * @constant
- */
- TERRAIN: 0,
- /**
- * Imagery request.
- *
- * @type Number
- * @constant
- */
- IMAGERY: 1,
- /**
- * 3D Tiles request.
- *
- * @type Number
- * @constant
- */
- TILES3D: 2,
- /**
- * Other request.
- *
- * @type Number
- * @constant
- */
- OTHER: 3,
- };
- var RequestType$1 = Object.freeze(RequestType);
- /**
- * Stores information for making a request. In general this does not need to be constructed directly.
- *
- * @alias Request
- * @constructor
- * @param {Object} [options] An object with the following properties:
- * @param {String} [options.url] The url to request.
- * @param {Request.RequestCallback} [options.requestFunction] The function that makes the actual data request.
- * @param {Request.CancelCallback} [options.cancelFunction] The function that is called when the request is cancelled.
- * @param {Request.PriorityCallback} [options.priorityFunction] The function that is called to update the request's priority, which occurs once per frame.
- * @param {Number} [options.priority=0.0] The initial priority of the request.
- * @param {Boolean} [options.throttle=false] Whether to throttle and prioritize the request. If false, the request will be sent immediately. If true, the request will be throttled and sent based on priority.
- * @param {Boolean} [options.throttleByServer=false] Whether to throttle the request by server.
- * @param {RequestType} [options.type=RequestType.OTHER] The type of request.
- */
- function Request(options) {
- options = when.defaultValue(options, when.defaultValue.EMPTY_OBJECT);
- var throttleByServer = when.defaultValue(options.throttleByServer, false);
- var throttle = when.defaultValue(options.throttle, false);
- /**
- * The URL to request.
- *
- * @type {String}
- */
- this.url = options.url;
- /**
- * The function that makes the actual data request.
- *
- * @type {Request.RequestCallback}
- */
- this.requestFunction = options.requestFunction;
- /**
- * The function that is called when the request is cancelled.
- *
- * @type {Request.CancelCallback}
- */
- this.cancelFunction = options.cancelFunction;
- /**
- * The function that is called to update the request's priority, which occurs once per frame.
- *
- * @type {Request.PriorityCallback}
- */
- this.priorityFunction = options.priorityFunction;
- /**
- * Priority is a unit-less value where lower values represent higher priority.
- * For world-based objects, this is usually the distance from the camera.
- * A request that does not have a priority function defaults to a priority of 0.
- *
- * If priorityFunction is defined, this value is updated every frame with the result of that call.
- *
- * @type {Number}
- * @default 0.0
- */
- this.priority = when.defaultValue(options.priority, 0.0);
- /**
- * Whether to throttle and prioritize the request. If false, the request will be sent immediately. If true, the
- * request will be throttled and sent based on priority.
- *
- * @type {Boolean}
- * @readonly
- *
- * @default false
- */
- this.throttle = throttle;
- /**
- * Whether to throttle the request by server. Browsers typically support about 6-8 parallel connections
- * for HTTP/1 servers, and an unlimited amount of connections for HTTP/2 servers. Setting this value
- * to <code>true</code> is preferable for requests going through HTTP/1 servers.
- *
- * @type {Boolean}
- * @readonly
- *
- * @default false
- */
- this.throttleByServer = throttleByServer;
- /**
- * Type of request.
- *
- * @type {RequestType}
- * @readonly
- *
- * @default RequestType.OTHER
- */
- this.type = when.defaultValue(options.type, RequestType$1.OTHER);
- /**
- * A key used to identify the server that a request is going to. It is derived from the url's authority and scheme.
- *
- * @type {String}
- *
- * @private
- */
- this.serverKey = undefined;
- /**
- * The current state of the request.
- *
- * @type {RequestState}
- * @readonly
- */
- this.state = RequestState$1.UNISSUED;
- /**
- * The requests's deferred promise.
- *
- * @type {Object}
- *
- * @private
- */
- this.deferred = undefined;
- /**
- * Whether the request was explicitly cancelled.
- *
- * @type {Boolean}
- *
- * @private
- */
- this.cancelled = false;
- }
- /**
- * Mark the request as cancelled.
- *
- * @private
- */
- Request.prototype.cancel = function () {
- this.cancelled = true;
- };
- /**
- * Duplicates a Request instance.
- *
- * @param {Request} [result] The object onto which to store the result.
- *
- * @returns {Request} The modified result parameter or a new Resource instance if one was not provided.
- */
- Request.prototype.clone = function (result) {
- if (!when.defined(result)) {
- return new Request(this);
- }
- result.url = this.url;
- result.requestFunction = this.requestFunction;
- result.cancelFunction = this.cancelFunction;
- result.priorityFunction = this.priorityFunction;
- result.priority = this.priority;
- result.throttle = this.throttle;
- result.throttleByServer = this.throttleByServer;
- result.type = this.type;
- result.serverKey = this.serverKey;
- // These get defaulted because the cloned request hasn't been issued
- result.state = this.RequestState.UNISSUED;
- result.deferred = undefined;
- result.cancelled = false;
- return result;
- };
- /**
- * Parses the result of XMLHttpRequest's getAllResponseHeaders() method into
- * a dictionary.
- *
- * @function parseResponseHeaders
- *
- * @param {String} headerString The header string returned by getAllResponseHeaders(). The format is
- * described here: http://www.w3.org/TR/XMLHttpRequest/#the-getallresponseheaders()-method
- * @returns {Object} A dictionary of key/value pairs, where each key is the name of a header and the corresponding value
- * is that header's value.
- *
- * @private
- */
- function parseResponseHeaders(headerString) {
- var headers = {};
- if (!headerString) {
- return headers;
- }
- var headerPairs = headerString.split("\u000d\u000a");
- for (var i = 0; i < headerPairs.length; ++i) {
- var headerPair = headerPairs[i];
- // Can't use split() here because it does the wrong thing
- // if the header value has the string ": " in it.
- var index = headerPair.indexOf("\u003a\u0020");
- if (index > 0) {
- var key = headerPair.substring(0, index);
- var val = headerPair.substring(index + 2);
- headers[key] = val;
- }
- }
- return headers;
- }
- /**
- * An event that is raised when a request encounters an error.
- *
- * @constructor
- * @alias RequestErrorEvent
- *
- * @param {Number} [statusCode] The HTTP error status code, such as 404.
- * @param {Object} [response] The response included along with the error.
- * @param {String|Object} [responseHeaders] The response headers, represented either as an object literal or as a
- * string in the format returned by XMLHttpRequest's getAllResponseHeaders() function.
- */
- function RequestErrorEvent(statusCode, response, responseHeaders) {
- /**
- * The HTTP error status code, such as 404. If the error does not have a particular
- * HTTP code, this property will be undefined.
- *
- * @type {Number}
- */
- this.statusCode = statusCode;
- /**
- * The response included along with the error. If the error does not include a response,
- * this property will be undefined.
- *
- * @type {Object}
- */
- this.response = response;
- /**
- * The headers included in the response, represented as an object literal of key/value pairs.
- * If the error does not include any headers, this property will be undefined.
- *
- * @type {Object}
- */
- this.responseHeaders = responseHeaders;
- if (typeof this.responseHeaders === "string") {
- this.responseHeaders = parseResponseHeaders(this.responseHeaders);
- }
- }
- /**
- * Creates a string representing this RequestErrorEvent.
- * @memberof RequestErrorEvent
- *
- * @returns {String} A string representing the provided RequestErrorEvent.
- */
- RequestErrorEvent.prototype.toString = function () {
- var str = "Request has failed.";
- if (when.defined(this.statusCode)) {
- str += " Status Code: " + this.statusCode;
- }
- return str;
- };
- /**
- * A generic utility class for managing subscribers for a particular event.
- * This class is usually instantiated inside of a container class and
- * exposed as a property for others to subscribe to.
- *
- * @alias Event
- * @constructor
- * @example
- * MyObject.prototype.myListener = function(arg1, arg2) {
- * this.myArg1Copy = arg1;
- * this.myArg2Copy = arg2;
- * }
- *
- * var myObjectInstance = new MyObject();
- * var evt = new Cesium.Event();
- * evt.addEventListener(MyObject.prototype.myListener, myObjectInstance);
- * evt.raiseEvent('1', '2');
- * evt.removeEventListener(MyObject.prototype.myListener);
- */
- function Event() {
- this._listeners = [];
- this._scopes = [];
- this._toRemove = [];
- this._insideRaiseEvent = false;
- }
- Object.defineProperties(Event.prototype, {
- /**
- * The number of listeners currently subscribed to the event.
- * @memberof Event.prototype
- * @type {Number}
- * @readonly
- */
- numberOfListeners: {
- get: function () {
- return this._listeners.length - this._toRemove.length;
- },
- },
- });
- /**
- * Registers a callback function to be executed whenever the event is raised.
- * An optional scope can be provided to serve as the <code>this</code> pointer
- * in which the function will execute.
- *
- * @param {Function} listener The function to be executed when the event is raised.
- * @param {Object} [scope] An optional object scope to serve as the <code>this</code>
- * pointer in which the listener function will execute.
- * @returns {Event.RemoveCallback} A function that will remove this event listener when invoked.
- *
- * @see Event#raiseEvent
- * @see Event#removeEventListener
- */
- Event.prototype.addEventListener = function (listener, scope) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.func("listener", listener);
- //>>includeEnd('debug');
- this._listeners.push(listener);
- this._scopes.push(scope);
- var event = this;
- return function () {
- event.removeEventListener(listener, scope);
- };
- };
- /**
- * Unregisters a previously registered callback.
- *
- * @param {Function} listener The function to be unregistered.
- * @param {Object} [scope] The scope that was originally passed to addEventListener.
- * @returns {Boolean} <code>true</code> if the listener was removed; <code>false</code> if the listener and scope are not registered with the event.
- *
- * @see Event#addEventListener
- * @see Event#raiseEvent
- */
- Event.prototype.removeEventListener = function (listener, scope) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.func("listener", listener);
- //>>includeEnd('debug');
- var listeners = this._listeners;
- var scopes = this._scopes;
- var index = -1;
- for (var i = 0; i < listeners.length; i++) {
- if (listeners[i] === listener && scopes[i] === scope) {
- index = i;
- break;
- }
- }
- if (index !== -1) {
- if (this._insideRaiseEvent) {
- //In order to allow removing an event subscription from within
- //a callback, we don't actually remove the items here. Instead
- //remember the index they are at and undefined their value.
- this._toRemove.push(index);
- listeners[index] = undefined;
- scopes[index] = undefined;
- } else {
- listeners.splice(index, 1);
- scopes.splice(index, 1);
- }
- return true;
- }
- return false;
- };
- function compareNumber(a, b) {
- return b - a;
- }
- /**
- * Raises the event by calling each registered listener with all supplied arguments.
- *
- * @param {...Object} arguments This method takes any number of parameters and passes them through to the listener functions.
- *
- * @see Event#addEventListener
- * @see Event#removeEventListener
- */
- Event.prototype.raiseEvent = function () {
- this._insideRaiseEvent = true;
- var i;
- var listeners = this._listeners;
- var scopes = this._scopes;
- var length = listeners.length;
- for (i = 0; i < length; i++) {
- var listener = listeners[i];
- if (when.defined(listener)) {
- listeners[i].apply(scopes[i], arguments);
- }
- }
- //Actually remove items removed in removeEventListener.
- var toRemove = this._toRemove;
- length = toRemove.length;
- if (length > 0) {
- toRemove.sort(compareNumber);
- for (i = 0; i < length; i++) {
- var index = toRemove[i];
- listeners.splice(index, 1);
- scopes.splice(index, 1);
- }
- toRemove.length = 0;
- }
- this._insideRaiseEvent = false;
- };
- /**
- * Array implementation of a heap.
- *
- * @alias Heap
- * @constructor
- * @private
- *
- * @param {Object} options Object with the following properties:
- * @param {Heap.ComparatorCallback} options.comparator The comparator to use for the heap. If comparator(a, b) is less than 0, sort a to a lower index than b, otherwise sort to a higher index.
- */
- function Heap(options) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("options", options);
- Check.Check.defined("options.comparator", options.comparator);
- //>>includeEnd('debug');
- this._comparator = options.comparator;
- this._array = [];
- this._length = 0;
- this._maximumLength = undefined;
- }
- Object.defineProperties(Heap.prototype, {
- /**
- * Gets the length of the heap.
- *
- * @memberof Heap.prototype
- *
- * @type {Number}
- * @readonly
- */
- length: {
- get: function () {
- return this._length;
- },
- },
- /**
- * Gets the internal array.
- *
- * @memberof Heap.prototype
- *
- * @type {Array}
- * @readonly
- */
- internalArray: {
- get: function () {
- return this._array;
- },
- },
- /**
- * Gets and sets the maximum length of the heap.
- *
- * @memberof Heap.prototype
- *
- * @type {Number}
- */
- maximumLength: {
- get: function () {
- return this._maximumLength;
- },
- set: function (value) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.number.greaterThanOrEquals("maximumLength", value, 0);
- //>>includeEnd('debug');
- var originalLength = this._length;
- if (value < originalLength) {
- var array = this._array;
- // Remove trailing references
- for (var i = value; i < originalLength; ++i) {
- array[i] = undefined;
- }
- this._length = value;
- array.length = value;
- }
- this._maximumLength = value;
- },
- },
- /**
- * The comparator to use for the heap. If comparator(a, b) is less than 0, sort a to a lower index than b, otherwise sort to a higher index.
- *
- * @memberof Heap.prototype
- *
- * @type {Heap.ComparatorCallback}
- */
- comparator: {
- get: function () {
- return this._comparator;
- },
- },
- });
- function swap(array, a, b) {
- var temp = array[a];
- array[a] = array[b];
- array[b] = temp;
- }
- /**
- * Resizes the internal array of the heap.
- *
- * @param {Number} [length] The length to resize internal array to. Defaults to the current length of the heap.
- */
- Heap.prototype.reserve = function (length) {
- length = when.defaultValue(length, this._length);
- this._array.length = length;
- };
- /**
- * Update the heap so that index and all descendants satisfy the heap property.
- *
- * @param {Number} [index=0] The starting index to heapify from.
- */
- Heap.prototype.heapify = function (index) {
- index = when.defaultValue(index, 0);
- var length = this._length;
- var comparator = this._comparator;
- var array = this._array;
- var candidate = -1;
- var inserting = true;
- while (inserting) {
- var right = 2 * (index + 1);
- var left = right - 1;
- if (left < length && comparator(array[left], array[index]) < 0) {
- candidate = left;
- } else {
- candidate = index;
- }
- if (right < length && comparator(array[right], array[candidate]) < 0) {
- candidate = right;
- }
- if (candidate !== index) {
- swap(array, candidate, index);
- index = candidate;
- } else {
- inserting = false;
- }
- }
- };
- /**
- * Resort the heap.
- */
- Heap.prototype.resort = function () {
- var length = this._length;
- for (var i = Math.ceil(length / 2); i >= 0; --i) {
- this.heapify(i);
- }
- };
- /**
- * Insert an element into the heap. If the length would grow greater than maximumLength
- * of the heap, extra elements are removed.
- *
- * @param {*} element The element to insert
- *
- * @return {*} The element that was removed from the heap if the heap is at full capacity.
- */
- Heap.prototype.insert = function (element) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.defined("element", element);
- //>>includeEnd('debug');
- var array = this._array;
- var comparator = this._comparator;
- var maximumLength = this._maximumLength;
- var index = this._length++;
- if (index < array.length) {
- array[index] = element;
- } else {
- array.push(element);
- }
- while (index !== 0) {
- var parent = Math.floor((index - 1) / 2);
- if (comparator(array[index], array[parent]) < 0) {
- swap(array, index, parent);
- index = parent;
- } else {
- break;
- }
- }
- var removedElement;
- if (when.defined(maximumLength) && this._length > maximumLength) {
- removedElement = array[maximumLength];
- this._length = maximumLength;
- }
- return removedElement;
- };
- /**
- * Remove the element specified by index from the heap and return it.
- *
- * @param {Number} [index=0] The index to remove.
- * @returns {*} The specified element of the heap.
- */
- Heap.prototype.pop = function (index) {
- index = when.defaultValue(index, 0);
- if (this._length === 0) {
- return undefined;
- }
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.number.lessThan("index", index, this._length);
- //>>includeEnd('debug');
- var array = this._array;
- var root = array[index];
- swap(array, index, --this._length);
- this.heapify(index);
- array[this._length] = undefined; // Remove trailing reference
- return root;
- };
- function sortRequests(a, b) {
- return a.priority - b.priority;
- }
- var statistics = {
- numberOfAttemptedRequests: 0,
- numberOfActiveRequests: 0,
- numberOfCancelledRequests: 0,
- numberOfCancelledActiveRequests: 0,
- numberOfFailedRequests: 0,
- numberOfActiveRequestsEver: 0,
- lastNumberOfActiveRequests: 0,
- };
- var priorityHeapLength = 20;
- var requestHeap = new Heap({
- comparator: sortRequests,
- });
- requestHeap.maximumLength = priorityHeapLength;
- requestHeap.reserve(priorityHeapLength);
- var activeRequests = [];
- var numberOfActiveRequestsByServer = {};
- var pageUri =
- typeof document !== "undefined" ? new URI(document.location.href) : new URI();
- var requestCompletedEvent = new Event();
- /**
- * The request scheduler is used to track and constrain the number of active requests in order to prioritize incoming requests. The ability
- * to retain control over the number of requests in CesiumJS is important because due to events such as changes in the camera position,
- * a lot of new requests may be generated and a lot of in-flight requests may become redundant. The request scheduler manually constrains the
- * number of requests so that newer requests wait in a shorter queue and don't have to compete for bandwidth with requests that have expired.
- *
- * @namespace RequestScheduler
- *
- */
- function RequestScheduler() {}
- /**
- * The maximum number of simultaneous active requests. Un-throttled requests do not observe this limit.
- * @type {Number}
- * @default 50
- */
- RequestScheduler.maximumRequests = 50;
- /**
- * The maximum number of simultaneous active requests per server. Un-throttled requests or servers specifically
- * listed in {@link requestsByServer} do not observe this limit.
- * @type {Number}
- * @default 6
- */
- RequestScheduler.maximumRequestsPerServer = 6;
- /**
- * A per server key list of overrides to use for throttling instead of <code>maximumRequestsPerServer</code>
- * @type {Object}
- *
- * @example
- * RequestScheduler.requestsByServer = {
- * 'api.cesium.com:443': 18,
- * 'assets.cesium.com:443': 18
- * };
- */
- RequestScheduler.requestsByServer = {
- "api.cesium.com:443": 18,
- "assets.cesium.com:443": 18,
- };
- /**
- * Specifies if the request scheduler should throttle incoming requests, or let the browser queue requests under its control.
- * @type {Boolean}
- * @default true
- */
- RequestScheduler.throttleRequests = true;
- /**
- * When true, log statistics to the console every frame
- * @type {Boolean}
- * @default false
- * @private
- */
- RequestScheduler.debugShowStatistics = false;
- /**
- * An event that's raised when a request is completed. Event handlers are passed
- * the error object if the request fails.
- *
- * @type {Event}
- * @default Event()
- * @private
- */
- RequestScheduler.requestCompletedEvent = requestCompletedEvent;
- Object.defineProperties(RequestScheduler, {
- /**
- * Returns the statistics used by the request scheduler.
- *
- * @memberof RequestScheduler
- *
- * @type Object
- * @readonly
- * @private
- */
- statistics: {
- get: function () {
- return statistics;
- },
- },
- /**
- * The maximum size of the priority heap. This limits the number of requests that are sorted by priority. Only applies to requests that are not yet active.
- *
- * @memberof RequestScheduler
- *
- * @type {Number}
- * @default 20
- * @private
- */
- priorityHeapLength: {
- get: function () {
- return priorityHeapLength;
- },
- set: function (value) {
- // If the new length shrinks the heap, need to cancel some of the requests.
- // Since this value is not intended to be tweaked regularly it is fine to just cancel the high priority requests.
- if (value < priorityHeapLength) {
- while (requestHeap.length > value) {
- var request = requestHeap.pop();
- cancelRequest(request);
- }
- }
- priorityHeapLength = value;
- requestHeap.maximumLength = value;
- requestHeap.reserve(value);
- },
- },
- });
- function updatePriority(request) {
- if (when.defined(request.priorityFunction)) {
- request.priority = request.priorityFunction();
- }
- }
- function serverHasOpenSlots(serverKey) {
- var maxRequests = when.defaultValue(
- RequestScheduler.requestsByServer[serverKey],
- RequestScheduler.maximumRequestsPerServer
- );
- return numberOfActiveRequestsByServer[serverKey] < maxRequests;
- }
- function issueRequest(request) {
- if (request.state === RequestState$1.UNISSUED) {
- request.state = RequestState$1.ISSUED;
- request.deferred = when.when.defer();
- }
- return request.deferred.promise;
- }
- function getRequestReceivedFunction(request) {
- return function (results) {
- if (request.state === RequestState$1.CANCELLED) {
- // If the data request comes back but the request is cancelled, ignore it.
- return;
- }
- --statistics.numberOfActiveRequests;
- --numberOfActiveRequestsByServer[request.serverKey];
- requestCompletedEvent.raiseEvent();
- request.state = RequestState$1.RECEIVED;
- request.deferred.resolve(results);
- // explicitly set to undefined to ensure GC of request response data. See #8843
- request.deferred = undefined;
- };
- }
- function getRequestFailedFunction(request) {
- return function (error) {
- if (request.state === RequestState$1.CANCELLED) {
- // If the data request comes back but the request is cancelled, ignore it.
- return;
- }
- ++statistics.numberOfFailedRequests;
- --statistics.numberOfActiveRequests;
- --numberOfActiveRequestsByServer[request.serverKey];
- requestCompletedEvent.raiseEvent(error);
- request.state = RequestState$1.FAILED;
- request.deferred.reject(error);
- };
- }
- function startRequest(request) {
- var promise = issueRequest(request);
- request.state = RequestState$1.ACTIVE;
- activeRequests.push(request);
- ++statistics.numberOfActiveRequests;
- ++statistics.numberOfActiveRequestsEver;
- ++numberOfActiveRequestsByServer[request.serverKey];
- request
- .requestFunction()
- .then(getRequestReceivedFunction(request))
- .otherwise(getRequestFailedFunction(request));
- return promise;
- }
- function cancelRequest(request) {
- var active = request.state === RequestState$1.ACTIVE;
- request.state = RequestState$1.CANCELLED;
- ++statistics.numberOfCancelledRequests;
- // check that deferred has not been cleared since cancelRequest can be called
- // on a finished request, e.g. by clearForSpecs during tests
- if (when.defined(request.deferred)) {
- request.deferred.reject();
- request.deferred = undefined;
- }
- if (active) {
- --statistics.numberOfActiveRequests;
- --numberOfActiveRequestsByServer[request.serverKey];
- ++statistics.numberOfCancelledActiveRequests;
- }
- if (when.defined(request.cancelFunction)) {
- request.cancelFunction();
- }
- }
- /**
- * Sort requests by priority and start requests.
- * @private
- */
- RequestScheduler.update = function () {
- var i;
- var request;
- // Loop over all active requests. Cancelled, failed, or received requests are removed from the array to make room for new requests.
- var removeCount = 0;
- var activeLength = activeRequests.length;
- for (i = 0; i < activeLength; ++i) {
- request = activeRequests[i];
- if (request.cancelled) {
- // Request was explicitly cancelled
- cancelRequest(request);
- }
- if (request.state !== RequestState$1.ACTIVE) {
- // Request is no longer active, remove from array
- ++removeCount;
- continue;
- }
- if (removeCount > 0) {
- // Shift back to fill in vacated slots from completed requests
- activeRequests[i - removeCount] = request;
- }
- }
- activeRequests.length -= removeCount;
- // Update priority of issued requests and resort the heap
- var issuedRequests = requestHeap.internalArray;
- var issuedLength = requestHeap.length;
- for (i = 0; i < issuedLength; ++i) {
- updatePriority(issuedRequests[i]);
- }
- requestHeap.resort();
- // Get the number of open slots and fill with the highest priority requests.
- // Un-throttled requests are automatically added to activeRequests, so activeRequests.length may exceed maximumRequests
- var openSlots = Math.max(
- RequestScheduler.maximumRequests - activeRequests.length,
- 0
- );
- var filledSlots = 0;
- while (filledSlots < openSlots && requestHeap.length > 0) {
- // Loop until all open slots are filled or the heap becomes empty
- request = requestHeap.pop();
- if (request.cancelled) {
- // Request was explicitly cancelled
- cancelRequest(request);
- continue;
- }
- if (request.throttleByServer && !serverHasOpenSlots(request.serverKey)) {
- // Open slots are available, but the request is throttled by its server. Cancel and try again later.
- cancelRequest(request);
- continue;
- }
- startRequest(request);
- ++filledSlots;
- }
- updateStatistics();
- };
- /**
- * Get the server key from a given url.
- *
- * @param {String} url The url.
- * @returns {String} The server key.
- * @private
- */
- RequestScheduler.getServerKey = function (url) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.string("url", url);
- //>>includeEnd('debug');
- var uri = new URI(url).resolve(pageUri);
- uri.normalize();
- var serverKey = uri.authority;
- if (!/:/.test(serverKey)) {
- // If the authority does not contain a port number, add port 443 for https or port 80 for http
- serverKey = serverKey + ":" + (uri.scheme === "https" ? "443" : "80");
- }
- var length = numberOfActiveRequestsByServer[serverKey];
- if (!when.defined(length)) {
- numberOfActiveRequestsByServer[serverKey] = 0;
- }
- return serverKey;
- };
- /**
- * Issue a request. If request.throttle is false, the request is sent immediately. Otherwise the request will be
- * queued and sorted by priority before being sent.
- *
- * @param {Request} request The request object.
- *
- * @returns {Promise|undefined} A Promise for the requested data, or undefined if this request does not have high enough priority to be issued.
- *
- * @private
- */
- RequestScheduler.request = function (request) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("request", request);
- Check.Check.typeOf.string("request.url", request.url);
- Check.Check.typeOf.func("request.requestFunction", request.requestFunction);
- //>>includeEnd('debug');
- if (isDataUri(request.url) || isBlobUri(request.url)) {
- requestCompletedEvent.raiseEvent();
- request.state = RequestState$1.RECEIVED;
- return request.requestFunction();
- }
- ++statistics.numberOfAttemptedRequests;
- if (!when.defined(request.serverKey)) {
- request.serverKey = RequestScheduler.getServerKey(request.url);
- }
- if (
- RequestScheduler.throttleRequests &&
- request.throttleByServer &&
- !serverHasOpenSlots(request.serverKey)
- ) {
- // Server is saturated. Try again later.
- return undefined;
- }
- if (!RequestScheduler.throttleRequests || !request.throttle) {
- return startRequest(request);
- }
- if (activeRequests.length >= RequestScheduler.maximumRequests) {
- // Active requests are saturated. Try again later.
- return undefined;
- }
- // Insert into the priority heap and see if a request was bumped off. If this request is the lowest
- // priority it will be returned.
- updatePriority(request);
- var removedRequest = requestHeap.insert(request);
- if (when.defined(removedRequest)) {
- if (removedRequest === request) {
- // Request does not have high enough priority to be issued
- return undefined;
- }
- // A previously issued request has been bumped off the priority heap, so cancel it
- cancelRequest(removedRequest);
- }
- return issueRequest(request);
- };
- function updateStatistics() {
- if (!RequestScheduler.debugShowStatistics) {
- return;
- }
- if (
- statistics.numberOfActiveRequests === 0 &&
- statistics.lastNumberOfActiveRequests > 0
- ) {
- if (statistics.numberOfAttemptedRequests > 0) {
- console.log(
- "Number of attempted requests: " + statistics.numberOfAttemptedRequests
- );
- statistics.numberOfAttemptedRequests = 0;
- }
- if (statistics.numberOfCancelledRequests > 0) {
- console.log(
- "Number of cancelled requests: " + statistics.numberOfCancelledRequests
- );
- statistics.numberOfCancelledRequests = 0;
- }
- if (statistics.numberOfCancelledActiveRequests > 0) {
- console.log(
- "Number of cancelled active requests: " +
- statistics.numberOfCancelledActiveRequests
- );
- statistics.numberOfCancelledActiveRequests = 0;
- }
- if (statistics.numberOfFailedRequests > 0) {
- console.log(
- "Number of failed requests: " + statistics.numberOfFailedRequests
- );
- statistics.numberOfFailedRequests = 0;
- }
- }
- statistics.lastNumberOfActiveRequests = statistics.numberOfActiveRequests;
- }
- /**
- * For testing only. Clears any requests that may not have completed from previous tests.
- *
- * @private
- */
- RequestScheduler.clearForSpecs = function () {
- while (requestHeap.length > 0) {
- var request = requestHeap.pop();
- cancelRequest(request);
- }
- var length = activeRequests.length;
- for (var i = 0; i < length; ++i) {
- cancelRequest(activeRequests[i]);
- }
- activeRequests.length = 0;
- numberOfActiveRequestsByServer = {};
- // Clear stats
- statistics.numberOfAttemptedRequests = 0;
- statistics.numberOfActiveRequests = 0;
- statistics.numberOfCancelledRequests = 0;
- statistics.numberOfCancelledActiveRequests = 0;
- statistics.numberOfFailedRequests = 0;
- statistics.numberOfActiveRequestsEver = 0;
- statistics.lastNumberOfActiveRequests = 0;
- };
- /**
- * For testing only.
- *
- * @private
- */
- RequestScheduler.numberOfActiveRequestsByServer = function (serverKey) {
- return numberOfActiveRequestsByServer[serverKey];
- };
- /**
- * For testing only.
- *
- * @private
- */
- RequestScheduler.requestHeap = requestHeap;
- /**
- * A singleton that contains all of the servers that are trusted. Credentials will be sent with
- * any requests to these servers.
- *
- * @namespace TrustedServers
- *
- * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}
- */
- var TrustedServers = {};
- var _servers = {};
- /**
- * Adds a trusted server to the registry
- *
- * @param {String} host The host to be added.
- * @param {Number} port The port used to access the host.
- *
- * @example
- * // Add a trusted server
- * TrustedServers.add('my.server.com', 80);
- */
- TrustedServers.add = function (host, port) {
- //>>includeStart('debug', pragmas.debug);
- if (!when.defined(host)) {
- throw new Check.DeveloperError("host is required.");
- }
- if (!when.defined(port) || port <= 0) {
- throw new Check.DeveloperError("port is required to be greater than 0.");
- }
- //>>includeEnd('debug');
- var authority = host.toLowerCase() + ":" + port;
- if (!when.defined(_servers[authority])) {
- _servers[authority] = true;
- }
- };
- /**
- * Removes a trusted server from the registry
- *
- * @param {String} host The host to be removed.
- * @param {Number} port The port used to access the host.
- *
- * @example
- * // Remove a trusted server
- * TrustedServers.remove('my.server.com', 80);
- */
- TrustedServers.remove = function (host, port) {
- //>>includeStart('debug', pragmas.debug);
- if (!when.defined(host)) {
- throw new Check.DeveloperError("host is required.");
- }
- if (!when.defined(port) || port <= 0) {
- throw new Check.DeveloperError("port is required to be greater than 0.");
- }
- //>>includeEnd('debug');
- var authority = host.toLowerCase() + ":" + port;
- if (when.defined(_servers[authority])) {
- delete _servers[authority];
- }
- };
- function getAuthority(url) {
- var uri = new URI(url);
- uri.normalize();
- // Removes username:password@ so we just have host[:port]
- var authority = uri.getAuthority();
- if (!when.defined(authority)) {
- return undefined; // Relative URL
- }
- if (authority.indexOf("@") !== -1) {
- var parts = authority.split("@");
- authority = parts[1];
- }
- // If the port is missing add one based on the scheme
- if (authority.indexOf(":") === -1) {
- var scheme = uri.getScheme();
- if (!when.defined(scheme)) {
- scheme = window.location.protocol;
- scheme = scheme.substring(0, scheme.length - 1);
- }
- if (scheme === "http") {
- authority += ":80";
- } else if (scheme === "https") {
- authority += ":443";
- } else {
- return undefined;
- }
- }
- return authority;
- }
- /**
- * Tests whether a server is trusted or not. The server must have been added with the port if it is included in the url.
- *
- * @param {String} url The url to be tested against the trusted list
- *
- * @returns {boolean} Returns true if url is trusted, false otherwise.
- *
- * @example
- * // Add server
- * TrustedServers.add('my.server.com', 81);
- *
- * // Check if server is trusted
- * if (TrustedServers.contains('https://my.server.com:81/path/to/file.png')) {
- * // my.server.com:81 is trusted
- * }
- * if (TrustedServers.contains('https://my.server.com/path/to/file.png')) {
- * // my.server.com isn't trusted
- * }
- */
- TrustedServers.contains = function (url) {
- //>>includeStart('debug', pragmas.debug);
- if (!when.defined(url)) {
- throw new Check.DeveloperError("url is required.");
- }
- //>>includeEnd('debug');
- var authority = getAuthority(url);
- if (when.defined(authority) && when.defined(_servers[authority])) {
- return true;
- }
- return false;
- };
- /**
- * Clears the registry
- *
- * @example
- * // Remove a trusted server
- * TrustedServers.clear();
- */
- TrustedServers.clear = function () {
- _servers = {};
- };
- var xhrBlobSupported = (function () {
- try {
- var xhr = new XMLHttpRequest();
- xhr.open("GET", "#", true);
- xhr.responseType = "blob";
- return xhr.responseType === "blob";
- } catch (e) {
- return false;
- }
- })();
- /**
- * Parses a query string and returns the object equivalent.
- *
- * @param {Uri} uri The Uri with a query object.
- * @param {Resource} resource The Resource that will be assigned queryParameters.
- * @param {Boolean} merge If true, we'll merge with the resource's existing queryParameters. Otherwise they will be replaced.
- * @param {Boolean} preserveQueryParameters If true duplicate parameters will be concatenated into an array. If false, keys in uri will take precedence.
- *
- * @private
- */
- function parseQuery(uri, resource, merge, preserveQueryParameters) {
- var queryString = uri.query;
- if (!when.defined(queryString) || queryString.length === 0) {
- return {};
- }
- var query;
- // Special case we run into where the querystring is just a string, not key/value pairs
- if (queryString.indexOf("=") === -1) {
- var result = {};
- result[queryString] = undefined;
- query = result;
- } else {
- query = queryToObject(queryString);
- }
- if (merge) {
- resource._queryParameters = combineQueryParameters(
- query,
- resource._queryParameters,
- preserveQueryParameters
- );
- } else {
- resource._queryParameters = query;
- }
- uri.query = undefined;
- }
- /**
- * Converts a query object into a string.
- *
- * @param {Uri} uri The Uri object that will have the query object set.
- * @param {Resource} resource The resource that has queryParameters
- *
- * @private
- */
- function stringifyQuery(uri, resource) {
- var queryObject = resource._queryParameters;
- var keys = Object.keys(queryObject);
- // We have 1 key with an undefined value, so this is just a string, not key/value pairs
- if (keys.length === 1 && !when.defined(queryObject[keys[0]])) {
- uri.query = keys[0];
- } else {
- uri.query = objectToQuery(queryObject);
- }
- }
- /**
- * Clones a value if it is defined, otherwise returns the default value
- *
- * @param {*} [val] The value to clone.
- * @param {*} [defaultVal] The default value.
- *
- * @returns {*} A clone of val or the defaultVal.
- *
- * @private
- */
- function defaultClone(val, defaultVal) {
- if (!when.defined(val)) {
- return defaultVal;
- }
- return when.defined(val.clone) ? val.clone() : clone(val);
- }
- /**
- * Checks to make sure the Resource isn't already being requested.
- *
- * @param {Request} request The request to check.
- *
- * @private
- */
- function checkAndResetRequest(request) {
- if (
- request.state === RequestState$1.ISSUED ||
- request.state === RequestState$1.ACTIVE
- ) {
- throw new RuntimeError.RuntimeError("The Resource is already being fetched.");
- }
- request.state = RequestState$1.UNISSUED;
- request.deferred = undefined;
- }
- /**
- * This combines a map of query parameters.
- *
- * @param {Object} q1 The first map of query parameters. Values in this map will take precedence if preserveQueryParameters is false.
- * @param {Object} q2 The second map of query parameters.
- * @param {Boolean} preserveQueryParameters If true duplicate parameters will be concatenated into an array. If false, keys in q1 will take precedence.
- *
- * @returns {Object} The combined map of query parameters.
- *
- * @example
- * var q1 = {
- * a: 1,
- * b: 2
- * };
- * var q2 = {
- * a: 3,
- * c: 4
- * };
- * var q3 = {
- * b: [5, 6],
- * d: 7
- * }
- *
- * // Returns
- * // {
- * // a: [1, 3],
- * // b: 2,
- * // c: 4
- * // };
- * combineQueryParameters(q1, q2, true);
- *
- * // Returns
- * // {
- * // a: 1,
- * // b: 2,
- * // c: 4
- * // };
- * combineQueryParameters(q1, q2, false);
- *
- * // Returns
- * // {
- * // a: 1,
- * // b: [2, 5, 6],
- * // d: 7
- * // };
- * combineQueryParameters(q1, q3, true);
- *
- * // Returns
- * // {
- * // a: 1,
- * // b: 2,
- * // d: 7
- * // };
- * combineQueryParameters(q1, q3, false);
- *
- * @private
- */
- function combineQueryParameters(q1, q2, preserveQueryParameters) {
- if (!preserveQueryParameters) {
- return combine(q1, q2);
- }
- var result = clone(q1, true);
- for (var param in q2) {
- if (q2.hasOwnProperty(param)) {
- var value = result[param];
- var q2Value = q2[param];
- if (when.defined(value)) {
- if (!Array.isArray(value)) {
- value = result[param] = [value];
- }
- result[param] = value.concat(q2Value);
- } else {
- result[param] = Array.isArray(q2Value) ? q2Value.slice() : q2Value;
- }
- }
- }
- return result;
- }
- /**
- * A resource that includes the location and any other parameters we need to retrieve it or create derived resources. It also provides the ability to retry requests.
- *
- * @alias Resource
- * @constructor
- *
- * @param {String|Object} options A url or an object with the following properties
- * @param {String} options.url The url of the resource.
- * @param {Object} [options.queryParameters] An object containing query parameters that will be sent when retrieving the resource.
- * @param {Object} [options.templateValues] Key/Value pairs that are used to replace template values (eg. {x}).
- * @param {Object} [options.headers={}] Additional HTTP headers that will be sent.
- * @param {Proxy} [options.proxy] A proxy to be used when loading the resource.
- * @param {Resource.RetryCallback} [options.retryCallback] The Function to call when a request for this resource fails. If it returns true, the request will be retried.
- * @param {Number} [options.retryAttempts=0] The number of times the retryCallback should be called before giving up.
- * @param {Request} [options.request] A Request object that will be used. Intended for internal use only.
- *
- * @example
- * function refreshTokenRetryCallback(resource, error) {
- * if (error.statusCode === 403) {
- * // 403 status code means a new token should be generated
- * return getNewAccessToken()
- * .then(function(token) {
- * resource.queryParameters.access_token = token;
- * return true;
- * })
- * .otherwise(function() {
- * return false;
- * });
- * }
- *
- * return false;
- * }
- *
- * var resource = new Resource({
- * url: 'http://server.com/path/to/resource.json',
- * proxy: new DefaultProxy('/proxy/'),
- * headers: {
- * 'X-My-Header': 'valueOfHeader'
- * },
- * queryParameters: {
- * 'access_token': '123-435-456-000'
- * },
- * retryCallback: refreshTokenRetryCallback,
- * retryAttempts: 1
- * });
- */
- function Resource(options) {
- options = when.defaultValue(options, when.defaultValue.EMPTY_OBJECT);
- if (typeof options === "string") {
- options = {
- url: options,
- };
- }
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.string("options.url", options.url);
- //>>includeEnd('debug');
- this._url = undefined;
- this._templateValues = defaultClone(options.templateValues, {});
- this._queryParameters = defaultClone(options.queryParameters, {});
- /**
- * Additional HTTP headers that will be sent with the request.
- *
- * @type {Object}
- */
- this.headers = defaultClone(options.headers, {});
- /**
- * A Request object that will be used. Intended for internal use only.
- *
- * @type {Request}
- */
- this.request = when.defaultValue(options.request, new Request());
- /**
- * A proxy to be used when loading the resource.
- *
- * @type {Proxy}
- */
- this.proxy = options.proxy;
- /**
- * Function to call when a request for this resource fails. If it returns true or a Promise that resolves to true, the request will be retried.
- *
- * @type {Function}
- */
- this.retryCallback = options.retryCallback;
- /**
- * The number of times the retryCallback should be called before giving up.
- *
- * @type {Number}
- */
- this.retryAttempts = when.defaultValue(options.retryAttempts, 0);
- this._retryCount = 0;
- var uri = new URI(options.url);
- parseQuery(uri, this, true, true);
- // Remove the fragment as it's not sent with a request
- uri.fragment = undefined;
- this._url = uri.toString();
- }
- /**
- * A helper function to create a resource depending on whether we have a String or a Resource
- *
- * @param {Resource|String} resource A Resource or a String to use when creating a new Resource.
- *
- * @returns {Resource} If resource is a String, a Resource constructed with the url and options. Otherwise the resource parameter is returned.
- *
- * @private
- */
- Resource.createIfNeeded = function (resource) {
- if (resource instanceof Resource) {
- // Keep existing request object. This function is used internally to duplicate a Resource, so that it can't
- // be modified outside of a class that holds it (eg. an imagery or terrain provider). Since the Request objects
- // are managed outside of the providers, by the tile loading code, we want to keep the request property the same so if it is changed
- // in the underlying tiling code the requests for this resource will use it.
- return resource.getDerivedResource({
- request: resource.request,
- });
- }
- if (typeof resource !== "string") {
- return resource;
- }
- return new Resource({
- url: resource,
- });
- };
- var supportsImageBitmapOptionsPromise;
- /**
- * A helper function to check whether createImageBitmap supports passing ImageBitmapOptions.
- *
- * @returns {Promise<Boolean>} A promise that resolves to true if this browser supports creating an ImageBitmap with options.
- *
- * @private
- */
- Resource.supportsImageBitmapOptions = function () {
- // Until the HTML folks figure out what to do about this, we need to actually try loading an image to
- // know if this browser supports passing options to the createImageBitmap function.
- // https://github.com/whatwg/html/pull/4248
- if (when.defined(supportsImageBitmapOptionsPromise)) {
- return supportsImageBitmapOptionsPromise;
- }
- if (typeof createImageBitmap !== "function") {
- supportsImageBitmapOptionsPromise = when.when.resolve(false);
- return supportsImageBitmapOptionsPromise;
- }
- var imageDataUri =
- "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWP4////fwAJ+wP9CNHoHgAAAABJRU5ErkJggg==";
- supportsImageBitmapOptionsPromise = Resource.fetchBlob({
- url: imageDataUri,
- })
- .then(function (blob) {
- return createImageBitmap(blob, {
- imageOrientation: "flipY",
- premultiplyAlpha: "none",
- });
- })
- .then(function (imageBitmap) {
- return true;
- })
- .otherwise(function () {
- return false;
- });
- return supportsImageBitmapOptionsPromise;
- };
- Object.defineProperties(Resource, {
- /**
- * Returns true if blobs are supported.
- *
- * @memberof Resource
- * @type {Boolean}
- *
- * @readonly
- */
- isBlobSupported: {
- get: function () {
- return xhrBlobSupported;
- },
- },
- });
- Object.defineProperties(Resource.prototype, {
- /**
- * Query parameters appended to the url.
- *
- * @memberof Resource.prototype
- * @type {Object}
- *
- * @readonly
- */
- queryParameters: {
- get: function () {
- return this._queryParameters;
- },
- },
- /**
- * The key/value pairs used to replace template parameters in the url.
- *
- * @memberof Resource.prototype
- * @type {Object}
- *
- * @readonly
- */
- templateValues: {
- get: function () {
- return this._templateValues;
- },
- },
- /**
- * The url to the resource with template values replaced, query string appended and encoded by proxy if one was set.
- *
- * @memberof Resource.prototype
- * @type {String}
- */
- url: {
- get: function () {
- return this.getUrlComponent(true, true);
- },
- set: function (value) {
- var uri = new URI(value);
- parseQuery(uri, this, false);
- // Remove the fragment as it's not sent with a request
- uri.fragment = undefined;
- this._url = uri.toString();
- },
- },
- /**
- * The file extension of the resource.
- *
- * @memberof Resource.prototype
- * @type {String}
- *
- * @readonly
- */
- extension: {
- get: function () {
- return getExtensionFromUri(this._url);
- },
- },
- /**
- * True if the Resource refers to a data URI.
- *
- * @memberof Resource.prototype
- * @type {Boolean}
- */
- isDataUri: {
- get: function () {
- return isDataUri(this._url);
- },
- },
- /**
- * True if the Resource refers to a blob URI.
- *
- * @memberof Resource.prototype
- * @type {Boolean}
- */
- isBlobUri: {
- get: function () {
- return isBlobUri(this._url);
- },
- },
- /**
- * True if the Resource refers to a cross origin URL.
- *
- * @memberof Resource.prototype
- * @type {Boolean}
- */
- isCrossOriginUrl: {
- get: function () {
- return isCrossOriginUrl(this._url);
- },
- },
- /**
- * True if the Resource has request headers. This is equivalent to checking if the headers property has any keys.
- *
- * @memberof Resource.prototype
- * @type {Boolean}
- */
- hasHeaders: {
- get: function () {
- return Object.keys(this.headers).length > 0;
- },
- },
- });
- /**
- * Override Object#toString so that implicit string conversion gives the
- * complete URL represented by this Resource.
- *
- * @returns {String} The URL represented by this Resource
- */
- Resource.prototype.toString = function () {
- return this.getUrlComponent(true, true);
- };
- /**
- * Returns the url, optional with the query string and processed by a proxy.
- *
- * @param {Boolean} [query=false] If true, the query string is included.
- * @param {Boolean} [proxy=false] If true, the url is processed by the proxy object, if defined.
- *
- * @returns {String} The url with all the requested components.
- */
- Resource.prototype.getUrlComponent = function (query, proxy) {
- if (this.isDataUri) {
- return this._url;
- }
- var uri = new URI(this._url);
- if (query) {
- stringifyQuery(uri, this);
- }
- // objectToQuery escapes the placeholders. Undo that.
- var url = uri.toString().replace(/%7B/g, "{").replace(/%7D/g, "}");
- var templateValues = this._templateValues;
- url = url.replace(/{(.*?)}/g, function (match, key) {
- var replacement = templateValues[key];
- if (when.defined(replacement)) {
- // use the replacement value from templateValues if there is one...
- return encodeURIComponent(replacement);
- }
- // otherwise leave it unchanged
- return match;
- });
- if (proxy && when.defined(this.proxy)) {
- url = this.proxy.getURL(url);
- }
- return url;
- };
- /**
- * Combines the specified object and the existing query parameters. This allows you to add many parameters at once,
- * as opposed to adding them one at a time to the queryParameters property. If a value is already set, it will be replaced with the new value.
- *
- * @param {Object} params The query parameters
- * @param {Boolean} [useAsDefault=false] If true the params will be used as the default values, so they will only be set if they are undefined.
- */
- Resource.prototype.setQueryParameters = function (params, useAsDefault) {
- if (useAsDefault) {
- this._queryParameters = combineQueryParameters(
- this._queryParameters,
- params,
- false
- );
- } else {
- this._queryParameters = combineQueryParameters(
- params,
- this._queryParameters,
- false
- );
- }
- };
- /**
- * Combines the specified object and the existing query parameters. This allows you to add many parameters at once,
- * as opposed to adding them one at a time to the queryParameters property.
- *
- * @param {Object} params The query parameters
- */
- Resource.prototype.appendQueryParameters = function (params) {
- this._queryParameters = combineQueryParameters(
- params,
- this._queryParameters,
- true
- );
- };
- /**
- * Combines the specified object and the existing template values. This allows you to add many values at once,
- * as opposed to adding them one at a time to the templateValues property. If a value is already set, it will become an array and the new value will be appended.
- *
- * @param {Object} template The template values
- * @param {Boolean} [useAsDefault=false] If true the values will be used as the default values, so they will only be set if they are undefined.
- */
- Resource.prototype.setTemplateValues = function (template, useAsDefault) {
- if (useAsDefault) {
- this._templateValues = combine(this._templateValues, template);
- } else {
- this._templateValues = combine(template, this._templateValues);
- }
- };
- /**
- * Returns a resource relative to the current instance. All properties remain the same as the current instance unless overridden in options.
- *
- * @param {Object} options An object with the following properties
- * @param {String} [options.url] The url that will be resolved relative to the url of the current instance.
- * @param {Object} [options.queryParameters] An object containing query parameters that will be combined with those of the current instance.
- * @param {Object} [options.templateValues] Key/Value pairs that are used to replace template values (eg. {x}). These will be combined with those of the current instance.
- * @param {Object} [options.headers={}] Additional HTTP headers that will be sent.
- * @param {Proxy} [options.proxy] A proxy to be used when loading the resource.
- * @param {Resource.RetryCallback} [options.retryCallback] The function to call when loading the resource fails.
- * @param {Number} [options.retryAttempts] The number of times the retryCallback should be called before giving up.
- * @param {Request} [options.request] A Request object that will be used. Intended for internal use only.
- * @param {Boolean} [options.preserveQueryParameters=false] If true, this will keep all query parameters from the current resource and derived resource. If false, derived parameters will replace those of the current resource.
- *
- * @returns {Resource} The resource derived from the current one.
- */
- Resource.prototype.getDerivedResource = function (options) {
- var resource = this.clone();
- resource._retryCount = 0;
- if (when.defined(options.url)) {
- var uri = new URI(options.url);
- var preserveQueryParameters = when.defaultValue(
- options.preserveQueryParameters,
- false
- );
- parseQuery(uri, resource, true, preserveQueryParameters);
- // Remove the fragment as it's not sent with a request
- uri.fragment = undefined;
- resource._url = uri.resolve(new URI(getAbsoluteUri(this._url))).toString();
- }
- if (when.defined(options.queryParameters)) {
- resource._queryParameters = combine(
- options.queryParameters,
- resource._queryParameters
- );
- }
- if (when.defined(options.templateValues)) {
- resource._templateValues = combine(
- options.templateValues,
- resource.templateValues
- );
- }
- if (when.defined(options.headers)) {
- resource.headers = combine(options.headers, resource.headers);
- }
- if (when.defined(options.proxy)) {
- resource.proxy = options.proxy;
- }
- if (when.defined(options.request)) {
- resource.request = options.request;
- }
- if (when.defined(options.retryCallback)) {
- resource.retryCallback = options.retryCallback;
- }
- if (when.defined(options.retryAttempts)) {
- resource.retryAttempts = options.retryAttempts;
- }
- return resource;
- };
- /**
- * Called when a resource fails to load. This will call the retryCallback function if defined until retryAttempts is reached.
- *
- * @param {Error} [error] The error that was encountered.
- *
- * @returns {Promise<Boolean>} A promise to a boolean, that if true will cause the resource request to be retried.
- *
- * @private
- */
- Resource.prototype.retryOnError = function (error) {
- var retryCallback = this.retryCallback;
- if (
- typeof retryCallback !== "function" ||
- this._retryCount >= this.retryAttempts
- ) {
- return when.when(false);
- }
- var that = this;
- return when.when(retryCallback(this, error)).then(function (result) {
- ++that._retryCount;
- return result;
- });
- };
- /**
- * Duplicates a Resource instance.
- *
- * @param {Resource} [result] The object onto which to store the result.
- *
- * @returns {Resource} The modified result parameter or a new Resource instance if one was not provided.
- */
- Resource.prototype.clone = function (result) {
- if (!when.defined(result)) {
- result = new Resource({
- url: this._url,
- });
- }
- result._url = this._url;
- result._queryParameters = clone(this._queryParameters);
- result._templateValues = clone(this._templateValues);
- result.headers = clone(this.headers);
- result.proxy = this.proxy;
- result.retryCallback = this.retryCallback;
- result.retryAttempts = this.retryAttempts;
- result._retryCount = 0;
- result.request = this.request.clone();
- return result;
- };
- /**
- * Returns the base path of the Resource.
- *
- * @param {Boolean} [includeQuery = false] Whether or not to include the query string and fragment form the uri
- *
- * @returns {String} The base URI of the resource
- */
- Resource.prototype.getBaseUri = function (includeQuery) {
- return getBaseUri(this.getUrlComponent(includeQuery), includeQuery);
- };
- /**
- * Appends a forward slash to the URL.
- */
- Resource.prototype.appendForwardSlash = function () {
- this._url = appendForwardSlash(this._url);
- };
- /**
- * Asynchronously loads the resource as raw binary data. Returns a promise that will resolve to
- * an ArrayBuffer once loaded, or reject if the resource failed to load. The data is loaded
- * using XMLHttpRequest, which means that in order to make requests to another origin,
- * the server must have Cross-Origin Resource Sharing (CORS) headers enabled.
- *
- * @returns {Promise.<ArrayBuffer>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if <code>request.throttle</code> is true and the request does not have high enough priority.
- *
- * @example
- * // load a single URL asynchronously
- * resource.fetchArrayBuffer().then(function(arrayBuffer) {
- * // use the data
- * }).otherwise(function(error) {
- * // an error occurred
- * });
- *
- * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}
- * @see {@link http://wiki.commonjs.org/wiki/Promises/A|CommonJS Promises/A}
- */
- Resource.prototype.fetchArrayBuffer = function () {
- return this.fetch({
- responseType: "arraybuffer",
- });
- };
- /**
- * Creates a Resource and calls fetchArrayBuffer() on it.
- *
- * @param {String|Object} options A url or an object with the following properties
- * @param {String} options.url The url of the resource.
- * @param {Object} [options.queryParameters] An object containing query parameters that will be sent when retrieving the resource.
- * @param {Object} [options.templateValues] Key/Value pairs that are used to replace template values (eg. {x}).
- * @param {Object} [options.headers={}] Additional HTTP headers that will be sent.
- * @param {Proxy} [options.proxy] A proxy to be used when loading the resource.
- * @param {Resource.RetryCallback} [options.retryCallback] The Function to call when a request for this resource fails. If it returns true, the request will be retried.
- * @param {Number} [options.retryAttempts=0] The number of times the retryCallback should be called before giving up.
- * @param {Request} [options.request] A Request object that will be used. Intended for internal use only.
- * @returns {Promise.<ArrayBuffer>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if <code>request.throttle</code> is true and the request does not have high enough priority.
- */
- Resource.fetchArrayBuffer = function (options) {
- var resource = new Resource(options);
- return resource.fetchArrayBuffer();
- };
- /**
- * Asynchronously loads the given resource as a blob. Returns a promise that will resolve to
- * a Blob once loaded, or reject if the resource failed to load. The data is loaded
- * using XMLHttpRequest, which means that in order to make requests to another origin,
- * the server must have Cross-Origin Resource Sharing (CORS) headers enabled.
- *
- * @returns {Promise.<Blob>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if <code>request.throttle</code> is true and the request does not have high enough priority.
- *
- * @example
- * // load a single URL asynchronously
- * resource.fetchBlob().then(function(blob) {
- * // use the data
- * }).otherwise(function(error) {
- * // an error occurred
- * });
- *
- * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}
- * @see {@link http://wiki.commonjs.org/wiki/Promises/A|CommonJS Promises/A}
- */
- Resource.prototype.fetchBlob = function () {
- return this.fetch({
- responseType: "blob",
- });
- };
- /**
- * Creates a Resource and calls fetchBlob() on it.
- *
- * @param {String|Object} options A url or an object with the following properties
- * @param {String} options.url The url of the resource.
- * @param {Object} [options.queryParameters] An object containing query parameters that will be sent when retrieving the resource.
- * @param {Object} [options.templateValues] Key/Value pairs that are used to replace template values (eg. {x}).
- * @param {Object} [options.headers={}] Additional HTTP headers that will be sent.
- * @param {Proxy} [options.proxy] A proxy to be used when loading the resource.
- * @param {Resource.RetryCallback} [options.retryCallback] The Function to call when a request for this resource fails. If it returns true, the request will be retried.
- * @param {Number} [options.retryAttempts=0] The number of times the retryCallback should be called before giving up.
- * @param {Request} [options.request] A Request object that will be used. Intended for internal use only.
- * @returns {Promise.<Blob>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if <code>request.throttle</code> is true and the request does not have high enough priority.
- */
- Resource.fetchBlob = function (options) {
- var resource = new Resource(options);
- return resource.fetchBlob();
- };
- /**
- * Asynchronously loads the given image resource. Returns a promise that will resolve to
- * an {@link https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap|ImageBitmap} if <code>preferImageBitmap</code> is true and the browser supports <code>createImageBitmap</code> or otherwise an
- * {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement|Image} once loaded, or reject if the image failed to load.
- *
- * @param {Object} [options] An object with the following properties.
- * @param {Boolean} [options.preferBlob=false] If true, we will load the image via a blob.
- * @param {Boolean} [options.preferImageBitmap=false] If true, image will be decoded during fetch and an <code>ImageBitmap</code> is returned.
- * @param {Boolean} [options.flipY=false] If true, image will be vertically flipped during decode. Only applies if the browser supports <code>createImageBitmap</code>.
- * @returns {Promise.<ImageBitmap>|Promise.<HTMLImageElement>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if <code>request.throttle</code> is true and the request does not have high enough priority.
- *
- *
- * @example
- * // load a single image asynchronously
- * resource.fetchImage().then(function(image) {
- * // use the loaded image
- * }).otherwise(function(error) {
- * // an error occurred
- * });
- *
- * // load several images in parallel
- * when.all([resource1.fetchImage(), resource2.fetchImage()]).then(function(images) {
- * // images is an array containing all the loaded images
- * });
- *
- * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}
- * @see {@link http://wiki.commonjs.org/wiki/Promises/A|CommonJS Promises/A}
- */
- Resource.prototype.fetchImage = function (options) {
- options = when.defaultValue(options, when.defaultValue.EMPTY_OBJECT);
- var preferImageBitmap = when.defaultValue(options.preferImageBitmap, false);
- var preferBlob = when.defaultValue(options.preferBlob, false);
- var flipY = when.defaultValue(options.flipY, false);
- checkAndResetRequest(this.request);
- // We try to load the image normally if
- // 1. Blobs aren't supported
- // 2. It's a data URI
- // 3. It's a blob URI
- // 4. It doesn't have request headers and we preferBlob is false
- if (
- !xhrBlobSupported ||
- this.isDataUri ||
- this.isBlobUri ||
- (!this.hasHeaders && !preferBlob)
- ) {
- return fetchImage({
- resource: this,
- flipY: flipY,
- preferImageBitmap: preferImageBitmap,
- });
- }
- var blobPromise = this.fetchBlob();
- if (!when.defined(blobPromise)) {
- return;
- }
- var supportsImageBitmap;
- var useImageBitmap;
- var generatedBlobResource;
- var generatedBlob;
- return Resource.supportsImageBitmapOptions()
- .then(function (result) {
- supportsImageBitmap = result;
- useImageBitmap = supportsImageBitmap && preferImageBitmap;
- return blobPromise;
- })
- .then(function (blob) {
- if (!when.defined(blob)) {
- return;
- }
- generatedBlob = blob;
- if (useImageBitmap) {
- return Resource.createImageBitmapFromBlob(blob, {
- flipY: flipY,
- premultiplyAlpha: false,
- });
- }
- var blobUrl = window.URL.createObjectURL(blob);
- generatedBlobResource = new Resource({
- url: blobUrl,
- });
- return fetchImage({
- resource: generatedBlobResource,
- flipY: flipY,
- preferImageBitmap: false,
- });
- })
- .then(function (image) {
- if (!when.defined(image)) {
- return;
- }
- // The blob object may be needed for use by a TileDiscardPolicy,
- // so attach it to the image.
- image.blob = generatedBlob;
- if (useImageBitmap) {
- return image;
- }
- window.URL.revokeObjectURL(generatedBlobResource.url);
- return image;
- })
- .otherwise(function (error) {
- if (when.defined(generatedBlobResource)) {
- window.URL.revokeObjectURL(generatedBlobResource.url);
- }
- // If the blob load succeeded but the image decode failed, attach the blob
- // to the error object for use by a TileDiscardPolicy.
- // In particular, BingMapsImageryProvider uses this to detect the
- // zero-length response that is returned when a tile is not available.
- error.blob = generatedBlob;
- return when.when.reject(error);
- });
- };
- /**
- * Fetches an image and returns a promise to it.
- *
- * @param {Object} [options] An object with the following properties.
- * @param {Resource} [options.resource] Resource object that points to an image to fetch.
- * @param {Boolean} [options.preferImageBitmap] If true, image will be decoded during fetch and an <code>ImageBitmap</code> is returned.
- * @param {Boolean} [options.flipY] If true, image will be vertically flipped during decode. Only applies if the browser supports <code>createImageBitmap</code>.
- *
- * @private
- */
- function fetchImage(options) {
- var resource = options.resource;
- var flipY = options.flipY;
- var preferImageBitmap = options.preferImageBitmap;
- var request = resource.request;
- request.url = resource.url;
- request.requestFunction = function () {
- var crossOrigin = false;
- // data URIs can't have crossorigin set.
- if (!resource.isDataUri && !resource.isBlobUri) {
- crossOrigin = resource.isCrossOriginUrl;
- }
- var deferred = when.when.defer();
- Resource._Implementations.createImage(
- request,
- crossOrigin,
- deferred,
- flipY,
- preferImageBitmap
- );
- return deferred.promise;
- };
- var promise = RequestScheduler.request(request);
- if (!when.defined(promise)) {
- return;
- }
- return promise.otherwise(function (e) {
- // Don't retry cancelled or otherwise aborted requests
- if (request.state !== RequestState$1.FAILED) {
- return when.when.reject(e);
- }
- return resource.retryOnError(e).then(function (retry) {
- if (retry) {
- // Reset request so it can try again
- request.state = RequestState$1.UNISSUED;
- request.deferred = undefined;
- return fetchImage({
- resource: resource,
- flipY: flipY,
- preferImageBitmap: preferImageBitmap,
- });
- }
- return when.when.reject(e);
- });
- });
- }
- /**
- * Creates a Resource and calls fetchImage() on it.
- *
- * @param {String|Object} options A url or an object with the following properties
- * @param {String} options.url The url of the resource.
- * @param {Object} [options.queryParameters] An object containing query parameters that will be sent when retrieving the resource.
- * @param {Object} [options.templateValues] Key/Value pairs that are used to replace template values (eg. {x}).
- * @param {Object} [options.headers={}] Additional HTTP headers that will be sent.
- * @param {Proxy} [options.proxy] A proxy to be used when loading the resource.
- * @param {Boolean} [options.flipY=false] Whether to vertically flip the image during fetch and decode. Only applies when requesting an image and the browser supports <code>createImageBitmap</code>.
- * @param {Resource.RetryCallback} [options.retryCallback] The Function to call when a request for this resource fails. If it returns true, the request will be retried.
- * @param {Number} [options.retryAttempts=0] The number of times the retryCallback should be called before giving up.
- * @param {Request} [options.request] A Request object that will be used. Intended for internal use only.
- * @param {Boolean} [options.preferBlob=false] If true, we will load the image via a blob.
- * @param {Boolean} [options.preferImageBitmap=false] If true, image will be decoded during fetch and an <code>ImageBitmap</code> is returned.
- * @returns {Promise.<ImageBitmap>|Promise.<HTMLImageElement>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if <code>request.throttle</code> is true and the request does not have high enough priority.
- */
- Resource.fetchImage = function (options) {
- var resource = new Resource(options);
- return resource.fetchImage({
- flipY: options.flipY,
- preferBlob: options.preferBlob,
- preferImageBitmap: options.preferImageBitmap,
- });
- };
- /**
- * Asynchronously loads the given resource as text. Returns a promise that will resolve to
- * a String once loaded, or reject if the resource failed to load. The data is loaded
- * using XMLHttpRequest, which means that in order to make requests to another origin,
- * the server must have Cross-Origin Resource Sharing (CORS) headers enabled.
- *
- * @returns {Promise.<String>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if <code>request.throttle</code> is true and the request does not have high enough priority.
- *
- * @example
- * // load text from a URL, setting a custom header
- * var resource = new Resource({
- * url: 'http://someUrl.com/someJson.txt',
- * headers: {
- * 'X-Custom-Header' : 'some value'
- * }
- * });
- * resource.fetchText().then(function(text) {
- * // Do something with the text
- * }).otherwise(function(error) {
- * // an error occurred
- * });
- *
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest|XMLHttpRequest}
- * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}
- * @see {@link http://wiki.commonjs.org/wiki/Promises/A|CommonJS Promises/A}
- */
- Resource.prototype.fetchText = function () {
- return this.fetch({
- responseType: "text",
- });
- };
- /**
- * Creates a Resource and calls fetchText() on it.
- *
- * @param {String|Object} options A url or an object with the following properties
- * @param {String} options.url The url of the resource.
- * @param {Object} [options.queryParameters] An object containing query parameters that will be sent when retrieving the resource.
- * @param {Object} [options.templateValues] Key/Value pairs that are used to replace template values (eg. {x}).
- * @param {Object} [options.headers={}] Additional HTTP headers that will be sent.
- * @param {Proxy} [options.proxy] A proxy to be used when loading the resource.
- * @param {Resource.RetryCallback} [options.retryCallback] The Function to call when a request for this resource fails. If it returns true, the request will be retried.
- * @param {Number} [options.retryAttempts=0] The number of times the retryCallback should be called before giving up.
- * @param {Request} [options.request] A Request object that will be used. Intended for internal use only.
- * @returns {Promise.<String>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if <code>request.throttle</code> is true and the request does not have high enough priority.
- */
- Resource.fetchText = function (options) {
- var resource = new Resource(options);
- return resource.fetchText();
- };
- // note: */* below is */* but that ends the comment block early
- /**
- * Asynchronously loads the given resource as JSON. Returns a promise that will resolve to
- * a JSON object once loaded, or reject if the resource failed to load. The data is loaded
- * using XMLHttpRequest, which means that in order to make requests to another origin,
- * the server must have Cross-Origin Resource Sharing (CORS) headers enabled. This function
- * adds 'Accept: application/json,*/*;q=0.01' to the request headers, if not
- * already specified.
- *
- * @returns {Promise.<*>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if <code>request.throttle</code> is true and the request does not have high enough priority.
- *
- *
- * @example
- * resource.fetchJson().then(function(jsonData) {
- * // Do something with the JSON object
- * }).otherwise(function(error) {
- * // an error occurred
- * });
- *
- * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}
- * @see {@link http://wiki.commonjs.org/wiki/Promises/A|CommonJS Promises/A}
- */
- Resource.prototype.fetchJson = function () {
- var promise = this.fetch({
- responseType: "text",
- headers: {
- Accept: "application/json,*/*;q=0.01",
- },
- });
- if (!when.defined(promise)) {
- return undefined;
- }
- return promise.then(function (value) {
- if (!when.defined(value)) {
- return;
- }
- return JSON.parse(value);
- });
- };
- /**
- * Creates a Resource and calls fetchJson() on it.
- *
- * @param {String|Object} options A url or an object with the following properties
- * @param {String} options.url The url of the resource.
- * @param {Object} [options.queryParameters] An object containing query parameters that will be sent when retrieving the resource.
- * @param {Object} [options.templateValues] Key/Value pairs that are used to replace template values (eg. {x}).
- * @param {Object} [options.headers={}] Additional HTTP headers that will be sent.
- * @param {Proxy} [options.proxy] A proxy to be used when loading the resource.
- * @param {Resource.RetryCallback} [options.retryCallback] The Function to call when a request for this resource fails. If it returns true, the request will be retried.
- * @param {Number} [options.retryAttempts=0] The number of times the retryCallback should be called before giving up.
- * @param {Request} [options.request] A Request object that will be used. Intended for internal use only.
- * @returns {Promise.<*>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if <code>request.throttle</code> is true and the request does not have high enough priority.
- */
- Resource.fetchJson = function (options) {
- var resource = new Resource(options);
- return resource.fetchJson();
- };
- /**
- * Asynchronously loads the given resource as XML. Returns a promise that will resolve to
- * an XML Document once loaded, or reject if the resource failed to load. The data is loaded
- * using XMLHttpRequest, which means that in order to make requests to another origin,
- * the server must have Cross-Origin Resource Sharing (CORS) headers enabled.
- *
- * @returns {Promise.<XMLDocument>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if <code>request.throttle</code> is true and the request does not have high enough priority.
- *
- *
- * @example
- * // load XML from a URL, setting a custom header
- * Cesium.loadXML('http://someUrl.com/someXML.xml', {
- * 'X-Custom-Header' : 'some value'
- * }).then(function(document) {
- * // Do something with the document
- * }).otherwise(function(error) {
- * // an error occurred
- * });
- *
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest|XMLHttpRequest}
- * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}
- * @see {@link http://wiki.commonjs.org/wiki/Promises/A|CommonJS Promises/A}
- */
- Resource.prototype.fetchXML = function () {
- return this.fetch({
- responseType: "document",
- overrideMimeType: "text/xml",
- });
- };
- /**
- * Creates a Resource and calls fetchXML() on it.
- *
- * @param {String|Object} options A url or an object with the following properties
- * @param {String} options.url The url of the resource.
- * @param {Object} [options.queryParameters] An object containing query parameters that will be sent when retrieving the resource.
- * @param {Object} [options.templateValues] Key/Value pairs that are used to replace template values (eg. {x}).
- * @param {Object} [options.headers={}] Additional HTTP headers that will be sent.
- * @param {Proxy} [options.proxy] A proxy to be used when loading the resource.
- * @param {Resource.RetryCallback} [options.retryCallback] The Function to call when a request for this resource fails. If it returns true, the request will be retried.
- * @param {Number} [options.retryAttempts=0] The number of times the retryCallback should be called before giving up.
- * @param {Request} [options.request] A Request object that will be used. Intended for internal use only.
- * @returns {Promise.<XMLDocument>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if <code>request.throttle</code> is true and the request does not have high enough priority.
- */
- Resource.fetchXML = function (options) {
- var resource = new Resource(options);
- return resource.fetchXML();
- };
- /**
- * Requests a resource using JSONP.
- *
- * @param {String} [callbackParameterName='callback'] The callback parameter name that the server expects.
- * @returns {Promise.<*>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if <code>request.throttle</code> is true and the request does not have high enough priority.
- *
- *
- * @example
- * // load a data asynchronously
- * resource.fetchJsonp().then(function(data) {
- * // use the loaded data
- * }).otherwise(function(error) {
- * // an error occurred
- * });
- *
- * @see {@link http://wiki.commonjs.org/wiki/Promises/A|CommonJS Promises/A}
- */
- Resource.prototype.fetchJsonp = function (callbackParameterName) {
- callbackParameterName = when.defaultValue(callbackParameterName, "callback");
- checkAndResetRequest(this.request);
- //generate a unique function name
- var functionName;
- do {
- functionName = "loadJsonp" + Math.random().toString().substring(2, 8);
- } while (when.defined(window[functionName]));
- return fetchJsonp(this, callbackParameterName, functionName);
- };
- function fetchJsonp(resource, callbackParameterName, functionName) {
- var callbackQuery = {};
- callbackQuery[callbackParameterName] = functionName;
- resource.setQueryParameters(callbackQuery);
- var request = resource.request;
- request.url = resource.url;
- request.requestFunction = function () {
- var deferred = when.when.defer();
- //assign a function with that name in the global scope
- window[functionName] = function (data) {
- deferred.resolve(data);
- try {
- delete window[functionName];
- } catch (e) {
- window[functionName] = undefined;
- }
- };
- Resource._Implementations.loadAndExecuteScript(
- resource.url,
- functionName,
- deferred
- );
- return deferred.promise;
- };
- var promise = RequestScheduler.request(request);
- if (!when.defined(promise)) {
- return;
- }
- return promise.otherwise(function (e) {
- if (request.state !== RequestState$1.FAILED) {
- return when.when.reject(e);
- }
- return resource.retryOnError(e).then(function (retry) {
- if (retry) {
- // Reset request so it can try again
- request.state = RequestState$1.UNISSUED;
- request.deferred = undefined;
- return fetchJsonp(resource, callbackParameterName, functionName);
- }
- return when.when.reject(e);
- });
- });
- }
- /**
- * Creates a Resource from a URL and calls fetchJsonp() on it.
- *
- * @param {String|Object} options A url or an object with the following properties
- * @param {String} options.url The url of the resource.
- * @param {Object} [options.queryParameters] An object containing query parameters that will be sent when retrieving the resource.
- * @param {Object} [options.templateValues] Key/Value pairs that are used to replace template values (eg. {x}).
- * @param {Object} [options.headers={}] Additional HTTP headers that will be sent.
- * @param {Proxy} [options.proxy] A proxy to be used when loading the resource.
- * @param {Resource.RetryCallback} [options.retryCallback] The Function to call when a request for this resource fails. If it returns true, the request will be retried.
- * @param {Number} [options.retryAttempts=0] The number of times the retryCallback should be called before giving up.
- * @param {Request} [options.request] A Request object that will be used. Intended for internal use only.
- * @param {String} [options.callbackParameterName='callback'] The callback parameter name that the server expects.
- * @returns {Promise.<*>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if <code>request.throttle</code> is true and the request does not have high enough priority.
- */
- Resource.fetchJsonp = function (options) {
- var resource = new Resource(options);
- return resource.fetchJsonp(options.callbackParameterName);
- };
- /**
- * @private
- */
- Resource.prototype._makeRequest = function (options) {
- var resource = this;
- checkAndResetRequest(resource.request);
- var request = resource.request;
- request.url = resource.url;
- request.requestFunction = function () {
- var responseType = options.responseType;
- var headers = combine(options.headers, resource.headers);
- var overrideMimeType = options.overrideMimeType;
- var method = options.method;
- var data = options.data;
- var deferred = when.when.defer();
- var xhr = Resource._Implementations.loadWithXhr(
- resource.url,
- responseType,
- method,
- data,
- headers,
- deferred,
- overrideMimeType
- );
- if (when.defined(xhr) && when.defined(xhr.abort)) {
- request.cancelFunction = function () {
- xhr.abort();
- };
- }
- return deferred.promise;
- };
- var promise = RequestScheduler.request(request);
- if (!when.defined(promise)) {
- return;
- }
- return promise
- .then(function (data) {
- // explicitly set to undefined to ensure GC of request response data. See #8843
- request.cancelFunction = undefined;
- return data;
- })
- .otherwise(function (e) {
- request.cancelFunction = undefined;
- if (request.state !== RequestState$1.FAILED) {
- return when.when.reject(e);
- }
- return resource.retryOnError(e).then(function (retry) {
- if (retry) {
- // Reset request so it can try again
- request.state = RequestState$1.UNISSUED;
- request.deferred = undefined;
- return resource.fetch(options);
- }
- return when.when.reject(e);
- });
- });
- };
- var dataUriRegex$1 = /^data:(.*?)(;base64)?,(.*)$/;
- function decodeDataUriText(isBase64, data) {
- var result = decodeURIComponent(data);
- if (isBase64) {
- return atob(result);
- }
- return result;
- }
- function decodeDataUriArrayBuffer(isBase64, data) {
- var byteString = decodeDataUriText(isBase64, data);
- var buffer = new ArrayBuffer(byteString.length);
- var view = new Uint8Array(buffer);
- for (var i = 0; i < byteString.length; i++) {
- view[i] = byteString.charCodeAt(i);
- }
- return buffer;
- }
- function decodeDataUri(dataUriRegexResult, responseType) {
- responseType = when.defaultValue(responseType, "");
- var mimeType = dataUriRegexResult[1];
- var isBase64 = !!dataUriRegexResult[2];
- var data = dataUriRegexResult[3];
- switch (responseType) {
- case "":
- case "text":
- return decodeDataUriText(isBase64, data);
- case "arraybuffer":
- return decodeDataUriArrayBuffer(isBase64, data);
- case "blob":
- var buffer = decodeDataUriArrayBuffer(isBase64, data);
- return new Blob([buffer], {
- type: mimeType,
- });
- case "document":
- var parser = new DOMParser();
- return parser.parseFromString(
- decodeDataUriText(isBase64, data),
- mimeType
- );
- case "json":
- return JSON.parse(decodeDataUriText(isBase64, data));
- default:
- //>>includeStart('debug', pragmas.debug);
- throw new Check.DeveloperError("Unhandled responseType: " + responseType);
- //>>includeEnd('debug');
- }
- }
- /**
- * Asynchronously loads the given resource. Returns a promise that will resolve to
- * the result once loaded, or reject if the resource failed to load. The data is loaded
- * using XMLHttpRequest, which means that in order to make requests to another origin,
- * the server must have Cross-Origin Resource Sharing (CORS) headers enabled. It's recommended that you use
- * the more specific functions eg. fetchJson, fetchBlob, etc.
- *
- * @param {Object} [options] Object with the following properties:
- * @param {String} [options.responseType] The type of response. This controls the type of item returned.
- * @param {Object} [options.headers] Additional HTTP headers to send with the request, if any.
- * @param {String} [options.overrideMimeType] Overrides the MIME type returned by the server.
- * @returns {Promise.<*>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if <code>request.throttle</code> is true and the request does not have high enough priority.
- *
- *
- * @example
- * resource.fetch()
- * .then(function(body) {
- * // use the data
- * }).otherwise(function(error) {
- * // an error occurred
- * });
- *
- * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}
- * @see {@link http://wiki.commonjs.org/wiki/Promises/A|CommonJS Promises/A}
- */
- Resource.prototype.fetch = function (options) {
- options = defaultClone(options, {});
- options.method = "GET";
- return this._makeRequest(options);
- };
- /**
- * Creates a Resource from a URL and calls fetch() on it.
- *
- * @param {String|Object} options A url or an object with the following properties
- * @param {String} options.url The url of the resource.
- * @param {Object} [options.queryParameters] An object containing query parameters that will be sent when retrieving the resource.
- * @param {Object} [options.templateValues] Key/Value pairs that are used to replace template values (eg. {x}).
- * @param {Object} [options.headers={}] Additional HTTP headers that will be sent.
- * @param {Proxy} [options.proxy] A proxy to be used when loading the resource.
- * @param {Resource.RetryCallback} [options.retryCallback] The Function to call when a request for this resource fails. If it returns true, the request will be retried.
- * @param {Number} [options.retryAttempts=0] The number of times the retryCallback should be called before giving up.
- * @param {Request} [options.request] A Request object that will be used. Intended for internal use only.
- * @param {String} [options.responseType] The type of response. This controls the type of item returned.
- * @param {String} [options.overrideMimeType] Overrides the MIME type returned by the server.
- * @returns {Promise.<*>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if <code>request.throttle</code> is true and the request does not have high enough priority.
- */
- Resource.fetch = function (options) {
- var resource = new Resource(options);
- return resource.fetch({
- // Make copy of just the needed fields because headers can be passed to both the constructor and to fetch
- responseType: options.responseType,
- overrideMimeType: options.overrideMimeType,
- });
- };
- /**
- * Asynchronously deletes the given resource. Returns a promise that will resolve to
- * the result once loaded, or reject if the resource failed to load. The data is loaded
- * using XMLHttpRequest, which means that in order to make requests to another origin,
- * the server must have Cross-Origin Resource Sharing (CORS) headers enabled.
- *
- * @param {Object} [options] Object with the following properties:
- * @param {String} [options.responseType] The type of response. This controls the type of item returned.
- * @param {Object} [options.headers] Additional HTTP headers to send with the request, if any.
- * @param {String} [options.overrideMimeType] Overrides the MIME type returned by the server.
- * @returns {Promise.<*>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if <code>request.throttle</code> is true and the request does not have high enough priority.
- *
- *
- * @example
- * resource.delete()
- * .then(function(body) {
- * // use the data
- * }).otherwise(function(error) {
- * // an error occurred
- * });
- *
- * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}
- * @see {@link http://wiki.commonjs.org/wiki/Promises/A|CommonJS Promises/A}
- */
- Resource.prototype.delete = function (options) {
- options = defaultClone(options, {});
- options.method = "DELETE";
- return this._makeRequest(options);
- };
- /**
- * Creates a Resource from a URL and calls delete() on it.
- *
- * @param {String|Object} options A url or an object with the following properties
- * @param {String} options.url The url of the resource.
- * @param {Object} [options.data] Data that is posted with the resource.
- * @param {Object} [options.queryParameters] An object containing query parameters that will be sent when retrieving the resource.
- * @param {Object} [options.templateValues] Key/Value pairs that are used to replace template values (eg. {x}).
- * @param {Object} [options.headers={}] Additional HTTP headers that will be sent.
- * @param {Proxy} [options.proxy] A proxy to be used when loading the resource.
- * @param {Resource.RetryCallback} [options.retryCallback] The Function to call when a request for this resource fails. If it returns true, the request will be retried.
- * @param {Number} [options.retryAttempts=0] The number of times the retryCallback should be called before giving up.
- * @param {Request} [options.request] A Request object that will be used. Intended for internal use only.
- * @param {String} [options.responseType] The type of response. This controls the type of item returned.
- * @param {String} [options.overrideMimeType] Overrides the MIME type returned by the server.
- * @returns {Promise.<*>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if <code>request.throttle</code> is true and the request does not have high enough priority.
- */
- Resource.delete = function (options) {
- var resource = new Resource(options);
- return resource.delete({
- // Make copy of just the needed fields because headers can be passed to both the constructor and to fetch
- responseType: options.responseType,
- overrideMimeType: options.overrideMimeType,
- data: options.data,
- });
- };
- /**
- * Asynchronously gets headers the given resource. Returns a promise that will resolve to
- * the result once loaded, or reject if the resource failed to load. The data is loaded
- * using XMLHttpRequest, which means that in order to make requests to another origin,
- * the server must have Cross-Origin Resource Sharing (CORS) headers enabled.
- *
- * @param {Object} [options] Object with the following properties:
- * @param {String} [options.responseType] The type of response. This controls the type of item returned.
- * @param {Object} [options.headers] Additional HTTP headers to send with the request, if any.
- * @param {String} [options.overrideMimeType] Overrides the MIME type returned by the server.
- * @returns {Promise.<*>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if <code>request.throttle</code> is true and the request does not have high enough priority.
- *
- *
- * @example
- * resource.head()
- * .then(function(headers) {
- * // use the data
- * }).otherwise(function(error) {
- * // an error occurred
- * });
- *
- * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}
- * @see {@link http://wiki.commonjs.org/wiki/Promises/A|CommonJS Promises/A}
- */
- Resource.prototype.head = function (options) {
- options = defaultClone(options, {});
- options.method = "HEAD";
- return this._makeRequest(options);
- };
- /**
- * Creates a Resource from a URL and calls head() on it.
- *
- * @param {String|Object} options A url or an object with the following properties
- * @param {String} options.url The url of the resource.
- * @param {Object} [options.queryParameters] An object containing query parameters that will be sent when retrieving the resource.
- * @param {Object} [options.templateValues] Key/Value pairs that are used to replace template values (eg. {x}).
- * @param {Object} [options.headers={}] Additional HTTP headers that will be sent.
- * @param {Proxy} [options.proxy] A proxy to be used when loading the resource.
- * @param {Resource.RetryCallback} [options.retryCallback] The Function to call when a request for this resource fails. If it returns true, the request will be retried.
- * @param {Number} [options.retryAttempts=0] The number of times the retryCallback should be called before giving up.
- * @param {Request} [options.request] A Request object that will be used. Intended for internal use only.
- * @param {String} [options.responseType] The type of response. This controls the type of item returned.
- * @param {String} [options.overrideMimeType] Overrides the MIME type returned by the server.
- * @returns {Promise.<*>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if <code>request.throttle</code> is true and the request does not have high enough priority.
- */
- Resource.head = function (options) {
- var resource = new Resource(options);
- return resource.head({
- // Make copy of just the needed fields because headers can be passed to both the constructor and to fetch
- responseType: options.responseType,
- overrideMimeType: options.overrideMimeType,
- });
- };
- /**
- * Asynchronously gets options the given resource. Returns a promise that will resolve to
- * the result once loaded, or reject if the resource failed to load. The data is loaded
- * using XMLHttpRequest, which means that in order to make requests to another origin,
- * the server must have Cross-Origin Resource Sharing (CORS) headers enabled.
- *
- * @param {Object} [options] Object with the following properties:
- * @param {String} [options.responseType] The type of response. This controls the type of item returned.
- * @param {Object} [options.headers] Additional HTTP headers to send with the request, if any.
- * @param {String} [options.overrideMimeType] Overrides the MIME type returned by the server.
- * @returns {Promise.<*>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if <code>request.throttle</code> is true and the request does not have high enough priority.
- *
- *
- * @example
- * resource.options()
- * .then(function(headers) {
- * // use the data
- * }).otherwise(function(error) {
- * // an error occurred
- * });
- *
- * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}
- * @see {@link http://wiki.commonjs.org/wiki/Promises/A|CommonJS Promises/A}
- */
- Resource.prototype.options = function (options) {
- options = defaultClone(options, {});
- options.method = "OPTIONS";
- return this._makeRequest(options);
- };
- /**
- * Creates a Resource from a URL and calls options() on it.
- *
- * @param {String|Object} options A url or an object with the following properties
- * @param {String} options.url The url of the resource.
- * @param {Object} [options.queryParameters] An object containing query parameters that will be sent when retrieving the resource.
- * @param {Object} [options.templateValues] Key/Value pairs that are used to replace template values (eg. {x}).
- * @param {Object} [options.headers={}] Additional HTTP headers that will be sent.
- * @param {Proxy} [options.proxy] A proxy to be used when loading the resource.
- * @param {Resource.RetryCallback} [options.retryCallback] The Function to call when a request for this resource fails. If it returns true, the request will be retried.
- * @param {Number} [options.retryAttempts=0] The number of times the retryCallback should be called before giving up.
- * @param {Request} [options.request] A Request object that will be used. Intended for internal use only.
- * @param {String} [options.responseType] The type of response. This controls the type of item returned.
- * @param {String} [options.overrideMimeType] Overrides the MIME type returned by the server.
- * @returns {Promise.<*>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if <code>request.throttle</code> is true and the request does not have high enough priority.
- */
- Resource.options = function (options) {
- var resource = new Resource(options);
- return resource.options({
- // Make copy of just the needed fields because headers can be passed to both the constructor and to fetch
- responseType: options.responseType,
- overrideMimeType: options.overrideMimeType,
- });
- };
- /**
- * Asynchronously posts data to the given resource. Returns a promise that will resolve to
- * the result once loaded, or reject if the resource failed to load. The data is loaded
- * using XMLHttpRequest, which means that in order to make requests to another origin,
- * the server must have Cross-Origin Resource Sharing (CORS) headers enabled.
- *
- * @param {Object} data Data that is posted with the resource.
- * @param {Object} [options] Object with the following properties:
- * @param {Object} [options.data] Data that is posted with the resource.
- * @param {String} [options.responseType] The type of response. This controls the type of item returned.
- * @param {Object} [options.headers] Additional HTTP headers to send with the request, if any.
- * @param {String} [options.overrideMimeType] Overrides the MIME type returned by the server.
- * @returns {Promise.<*>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if <code>request.throttle</code> is true and the request does not have high enough priority.
- *
- *
- * @example
- * resource.post(data)
- * .then(function(result) {
- * // use the result
- * }).otherwise(function(error) {
- * // an error occurred
- * });
- *
- * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}
- * @see {@link http://wiki.commonjs.org/wiki/Promises/A|CommonJS Promises/A}
- */
- Resource.prototype.post = function (data, options) {
- Check.Check.defined("data", data);
- options = defaultClone(options, {});
- options.method = "POST";
- options.data = data;
- return this._makeRequest(options);
- };
- /**
- * Creates a Resource from a URL and calls post() on it.
- *
- * @param {Object} options A url or an object with the following properties
- * @param {String} options.url The url of the resource.
- * @param {Object} options.data Data that is posted with the resource.
- * @param {Object} [options.queryParameters] An object containing query parameters that will be sent when retrieving the resource.
- * @param {Object} [options.templateValues] Key/Value pairs that are used to replace template values (eg. {x}).
- * @param {Object} [options.headers={}] Additional HTTP headers that will be sent.
- * @param {Proxy} [options.proxy] A proxy to be used when loading the resource.
- * @param {Resource.RetryCallback} [options.retryCallback] The Function to call when a request for this resource fails. If it returns true, the request will be retried.
- * @param {Number} [options.retryAttempts=0] The number of times the retryCallback should be called before giving up.
- * @param {Request} [options.request] A Request object that will be used. Intended for internal use only.
- * @param {String} [options.responseType] The type of response. This controls the type of item returned.
- * @param {String} [options.overrideMimeType] Overrides the MIME type returned by the server.
- * @returns {Promise.<*>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if <code>request.throttle</code> is true and the request does not have high enough priority.
- */
- Resource.post = function (options) {
- var resource = new Resource(options);
- return resource.post(options.data, {
- // Make copy of just the needed fields because headers can be passed to both the constructor and to post
- responseType: options.responseType,
- overrideMimeType: options.overrideMimeType,
- });
- };
- /**
- * Asynchronously puts data to the given resource. Returns a promise that will resolve to
- * the result once loaded, or reject if the resource failed to load. The data is loaded
- * using XMLHttpRequest, which means that in order to make requests to another origin,
- * the server must have Cross-Origin Resource Sharing (CORS) headers enabled.
- *
- * @param {Object} data Data that is posted with the resource.
- * @param {Object} [options] Object with the following properties:
- * @param {String} [options.responseType] The type of response. This controls the type of item returned.
- * @param {Object} [options.headers] Additional HTTP headers to send with the request, if any.
- * @param {String} [options.overrideMimeType] Overrides the MIME type returned by the server.
- * @returns {Promise.<*>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if <code>request.throttle</code> is true and the request does not have high enough priority.
- *
- *
- * @example
- * resource.put(data)
- * .then(function(result) {
- * // use the result
- * }).otherwise(function(error) {
- * // an error occurred
- * });
- *
- * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}
- * @see {@link http://wiki.commonjs.org/wiki/Promises/A|CommonJS Promises/A}
- */
- Resource.prototype.put = function (data, options) {
- Check.Check.defined("data", data);
- options = defaultClone(options, {});
- options.method = "PUT";
- options.data = data;
- return this._makeRequest(options);
- };
- /**
- * Creates a Resource from a URL and calls put() on it.
- *
- * @param {Object} options A url or an object with the following properties
- * @param {String} options.url The url of the resource.
- * @param {Object} options.data Data that is posted with the resource.
- * @param {Object} [options.queryParameters] An object containing query parameters that will be sent when retrieving the resource.
- * @param {Object} [options.templateValues] Key/Value pairs that are used to replace template values (eg. {x}).
- * @param {Object} [options.headers={}] Additional HTTP headers that will be sent.
- * @param {Proxy} [options.proxy] A proxy to be used when loading the resource.
- * @param {Resource.RetryCallback} [options.retryCallback] The Function to call when a request for this resource fails. If it returns true, the request will be retried.
- * @param {Number} [options.retryAttempts=0] The number of times the retryCallback should be called before giving up.
- * @param {Request} [options.request] A Request object that will be used. Intended for internal use only.
- * @param {String} [options.responseType] The type of response. This controls the type of item returned.
- * @param {String} [options.overrideMimeType] Overrides the MIME type returned by the server.
- * @returns {Promise.<*>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if <code>request.throttle</code> is true and the request does not have high enough priority.
- */
- Resource.put = function (options) {
- var resource = new Resource(options);
- return resource.put(options.data, {
- // Make copy of just the needed fields because headers can be passed to both the constructor and to post
- responseType: options.responseType,
- overrideMimeType: options.overrideMimeType,
- });
- };
- /**
- * Asynchronously patches data to the given resource. Returns a promise that will resolve to
- * the result once loaded, or reject if the resource failed to load. The data is loaded
- * using XMLHttpRequest, which means that in order to make requests to another origin,
- * the server must have Cross-Origin Resource Sharing (CORS) headers enabled.
- *
- * @param {Object} data Data that is posted with the resource.
- * @param {Object} [options] Object with the following properties:
- * @param {String} [options.responseType] The type of response. This controls the type of item returned.
- * @param {Object} [options.headers] Additional HTTP headers to send with the request, if any.
- * @param {String} [options.overrideMimeType] Overrides the MIME type returned by the server.
- * @returns {Promise.<*>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if <code>request.throttle</code> is true and the request does not have high enough priority.
- *
- *
- * @example
- * resource.patch(data)
- * .then(function(result) {
- * // use the result
- * }).otherwise(function(error) {
- * // an error occurred
- * });
- *
- * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}
- * @see {@link http://wiki.commonjs.org/wiki/Promises/A|CommonJS Promises/A}
- */
- Resource.prototype.patch = function (data, options) {
- Check.Check.defined("data", data);
- options = defaultClone(options, {});
- options.method = "PATCH";
- options.data = data;
- return this._makeRequest(options);
- };
- /**
- * Creates a Resource from a URL and calls patch() on it.
- *
- * @param {Object} options A url or an object with the following properties
- * @param {String} options.url The url of the resource.
- * @param {Object} options.data Data that is posted with the resource.
- * @param {Object} [options.queryParameters] An object containing query parameters that will be sent when retrieving the resource.
- * @param {Object} [options.templateValues] Key/Value pairs that are used to replace template values (eg. {x}).
- * @param {Object} [options.headers={}] Additional HTTP headers that will be sent.
- * @param {Proxy} [options.proxy] A proxy to be used when loading the resource.
- * @param {Resource.RetryCallback} [options.retryCallback] The Function to call when a request for this resource fails. If it returns true, the request will be retried.
- * @param {Number} [options.retryAttempts=0] The number of times the retryCallback should be called before giving up.
- * @param {Request} [options.request] A Request object that will be used. Intended for internal use only.
- * @param {String} [options.responseType] The type of response. This controls the type of item returned.
- * @param {String} [options.overrideMimeType] Overrides the MIME type returned by the server.
- * @returns {Promise.<*>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if <code>request.throttle</code> is true and the request does not have high enough priority.
- */
- Resource.patch = function (options) {
- var resource = new Resource(options);
- return resource.patch(options.data, {
- // Make copy of just the needed fields because headers can be passed to both the constructor and to post
- responseType: options.responseType,
- overrideMimeType: options.overrideMimeType,
- });
- };
- /**
- * Contains implementations of functions that can be replaced for testing
- *
- * @private
- */
- Resource._Implementations = {};
- function loadImageElement(url, crossOrigin, deferred) {
- var image = new Image();
- image.onload = function () {
- deferred.resolve(image);
- };
- image.onerror = function (e) {
- deferred.reject(e);
- };
- if (crossOrigin) {
- if (TrustedServers.contains(url)) {
- image.crossOrigin = "use-credentials";
- } else {
- image.crossOrigin = "";
- }
- }
- image.src = url;
- }
- Resource._Implementations.createImage = function (
- request,
- crossOrigin,
- deferred,
- flipY,
- preferImageBitmap
- ) {
- var url = request.url;
- // Passing an Image to createImageBitmap will force it to run on the main thread
- // since DOM elements don't exist on workers. We convert it to a blob so it's non-blocking.
- // See:
- // https://bugzilla.mozilla.org/show_bug.cgi?id=1044102#c38
- // https://bugs.chromium.org/p/chromium/issues/detail?id=580202#c10
- Resource.supportsImageBitmapOptions()
- .then(function (supportsImageBitmap) {
- // We can only use ImageBitmap if we can flip on decode.
- // See: https://github.com/CesiumGS/cesium/pull/7579#issuecomment-466146898
- if (!(supportsImageBitmap && preferImageBitmap)) {
- loadImageElement(url, crossOrigin, deferred);
- return;
- }
- var responseType = "blob";
- var method = "GET";
- var xhrDeferred = when.when.defer();
- var xhr = Resource._Implementations.loadWithXhr(
- url,
- responseType,
- method,
- undefined,
- undefined,
- xhrDeferred,
- undefined,
- undefined,
- undefined
- );
- if (when.defined(xhr) && when.defined(xhr.abort)) {
- request.cancelFunction = function () {
- xhr.abort();
- };
- }
- return xhrDeferred.promise
- .then(function (blob) {
- if (!when.defined(blob)) {
- deferred.reject(
- new RuntimeError.RuntimeError(
- "Successfully retrieved " +
- url +
- " but it contained no content."
- )
- );
- return;
- }
- return Resource.createImageBitmapFromBlob(blob, {
- flipY: flipY,
- premultiplyAlpha: false,
- });
- })
- .then(deferred.resolve);
- })
- .otherwise(deferred.reject);
- };
- /**
- * Wrapper for createImageBitmap
- *
- * @private
- */
- Resource.createImageBitmapFromBlob = function (blob, options) {
- Check.Check.defined("options", options);
- Check.Check.typeOf.bool("options.flipY", options.flipY);
- Check.Check.typeOf.bool("options.premultiplyAlpha", options.premultiplyAlpha);
- return createImageBitmap(blob, {
- imageOrientation: options.flipY ? "flipY" : "none",
- premultiplyAlpha: options.premultiplyAlpha ? "premultiply" : "none",
- });
- };
- function decodeResponse(loadWithHttpResponse, responseType) {
- switch (responseType) {
- case "text":
- return loadWithHttpResponse.toString("utf8");
- case "json":
- return JSON.parse(loadWithHttpResponse.toString("utf8"));
- default:
- return new Uint8Array(loadWithHttpResponse).buffer;
- }
- }
- function loadWithHttpRequest(
- url,
- responseType,
- method,
- data,
- headers,
- deferred,
- overrideMimeType
- ) {
- // Note: only the 'json' and 'text' responseTypes transforms the loaded buffer
- /* eslint-disable no-undef */
- var URL = require("url").parse(url);
- var http = URL.protocol === "https:" ? require("https") : require("http");
- var zlib = require("zlib");
- /* eslint-enable no-undef */
- var options = {
- protocol: URL.protocol,
- hostname: URL.hostname,
- port: URL.port,
- path: URL.path,
- query: URL.query,
- method: method,
- headers: headers,
- };
- http
- .request(options)
- .on("response", function (res) {
- if (res.statusCode < 200 || res.statusCode >= 300) {
- deferred.reject(
- new RequestErrorEvent(res.statusCode, res, res.headers)
- );
- return;
- }
- var chunkArray = [];
- res.on("data", function (chunk) {
- chunkArray.push(chunk);
- });
- res.on("end", function () {
- // eslint-disable-next-line no-undef
- var result = Buffer.concat(chunkArray);
- if (res.headers["content-encoding"] === "gzip") {
- zlib.gunzip(result, function (error, resultUnzipped) {
- if (error) {
- deferred.reject(
- new RuntimeError.RuntimeError("Error decompressing response.")
- );
- } else {
- deferred.resolve(decodeResponse(resultUnzipped, responseType));
- }
- });
- } else {
- deferred.resolve(decodeResponse(result, responseType));
- }
- });
- })
- .on("error", function (e) {
- deferred.reject(new RequestErrorEvent());
- })
- .end();
- }
- var noXMLHttpRequest = typeof XMLHttpRequest === "undefined";
- Resource._Implementations.loadWithXhr = function (
- url,
- responseType,
- method,
- data,
- headers,
- deferred,
- overrideMimeType
- ) {
- var dataUriRegexResult = dataUriRegex$1.exec(url);
- if (dataUriRegexResult !== null) {
- deferred.resolve(decodeDataUri(dataUriRegexResult, responseType));
- return;
- }
- if (noXMLHttpRequest) {
- loadWithHttpRequest(
- url,
- responseType,
- method,
- data,
- headers,
- deferred);
- return;
- }
- var xhr = new XMLHttpRequest();
- if (TrustedServers.contains(url)) {
- xhr.withCredentials = true;
- }
- xhr.open(method, url, true);
- if (when.defined(overrideMimeType) && when.defined(xhr.overrideMimeType)) {
- xhr.overrideMimeType(overrideMimeType);
- }
- if (when.defined(headers)) {
- for (var key in headers) {
- if (headers.hasOwnProperty(key)) {
- xhr.setRequestHeader(key, headers[key]);
- }
- }
- }
- if (when.defined(responseType)) {
- xhr.responseType = responseType;
- }
- // While non-standard, file protocol always returns a status of 0 on success
- var localFile = false;
- if (typeof url === "string") {
- localFile =
- url.indexOf("file://") === 0 ||
- (typeof window !== "undefined" && window.location.origin === "file://");
- }
- xhr.onload = function () {
- if (
- (xhr.status < 200 || xhr.status >= 300) &&
- !(localFile && xhr.status === 0)
- ) {
- deferred.reject(
- new RequestErrorEvent(
- xhr.status,
- xhr.response,
- xhr.getAllResponseHeaders()
- )
- );
- return;
- }
- var response = xhr.response;
- var browserResponseType = xhr.responseType;
- if (method === "HEAD" || method === "OPTIONS") {
- var responseHeaderString = xhr.getAllResponseHeaders();
- var splitHeaders = responseHeaderString.trim().split(/[\r\n]+/);
- var responseHeaders = {};
- splitHeaders.forEach(function (line) {
- var parts = line.split(": ");
- var header = parts.shift();
- responseHeaders[header] = parts.join(": ");
- });
- deferred.resolve(responseHeaders);
- return;
- }
- //All modern browsers will go into either the first or second if block or last else block.
- //Other code paths support older browsers that either do not support the supplied responseType
- //or do not support the xhr.response property.
- if (xhr.status === 204) {
- // accept no content
- deferred.resolve();
- } else if (
- when.defined(response) &&
- (!when.defined(responseType) || browserResponseType === responseType)
- ) {
- deferred.resolve(response);
- } else if (responseType === "json" && typeof response === "string") {
- try {
- deferred.resolve(JSON.parse(response));
- } catch (e) {
- deferred.reject(e);
- }
- } else if (
- (browserResponseType === "" || browserResponseType === "document") &&
- when.defined(xhr.responseXML) &&
- xhr.responseXML.hasChildNodes()
- ) {
- deferred.resolve(xhr.responseXML);
- } else if (
- (browserResponseType === "" || browserResponseType === "text") &&
- when.defined(xhr.responseText)
- ) {
- deferred.resolve(xhr.responseText);
- } else {
- deferred.reject(
- new RuntimeError.RuntimeError("Invalid XMLHttpRequest response type.")
- );
- }
- };
- xhr.onerror = function (e) {
- deferred.reject(new RequestErrorEvent());
- };
- xhr.send(data);
- return xhr;
- };
- Resource._Implementations.loadAndExecuteScript = function (
- url,
- functionName,
- deferred
- ) {
- return loadAndExecuteScript(url).otherwise(deferred.reject);
- };
- /**
- * The default implementations
- *
- * @private
- */
- Resource._DefaultImplementations = {};
- Resource._DefaultImplementations.createImage =
- Resource._Implementations.createImage;
- Resource._DefaultImplementations.loadWithXhr =
- Resource._Implementations.loadWithXhr;
- Resource._DefaultImplementations.loadAndExecuteScript =
- Resource._Implementations.loadAndExecuteScript;
- /**
- * A resource instance initialized to the current browser location
- *
- * @type {Resource}
- * @constant
- */
- Resource.DEFAULT = Object.freeze(
- new Resource({
- url:
- typeof document === "undefined"
- ? ""
- : document.location.href.split("?")[0],
- })
- );
- /**
- * Specifies Earth polar motion coordinates and the difference between UT1 and UTC.
- * These Earth Orientation Parameters (EOP) are primarily used in the transformation from
- * the International Celestial Reference Frame (ICRF) to the International Terrestrial
- * Reference Frame (ITRF).
- *
- * @alias EarthOrientationParameters
- * @constructor
- *
- * @param {Object} [options] Object with the following properties:
- * @param {Resource|String} [options.url] The URL from which to obtain EOP data. If neither this
- * parameter nor options.data is specified, all EOP values are assumed
- * to be 0.0. If options.data is specified, this parameter is
- * ignored.
- * @param {Object} [options.data] The actual EOP data. If neither this
- * parameter nor options.data is specified, all EOP values are assumed
- * to be 0.0.
- * @param {Boolean} [options.addNewLeapSeconds=true] True if leap seconds that
- * are specified in the EOP data but not in {@link JulianDate.leapSeconds}
- * should be added to {@link JulianDate.leapSeconds}. False if
- * new leap seconds should be handled correctly in the context
- * of the EOP data but otherwise ignored.
- *
- * @example
- * // An example EOP data file, EOP.json:
- * {
- * "columnNames" : ["dateIso8601","modifiedJulianDateUtc","xPoleWanderRadians","yPoleWanderRadians","ut1MinusUtcSeconds","lengthOfDayCorrectionSeconds","xCelestialPoleOffsetRadians","yCelestialPoleOffsetRadians","taiMinusUtcSeconds"],
- * "samples" : [
- * "2011-07-01T00:00:00Z",55743.0,2.117957047295119e-7,2.111518721609984e-6,-0.2908948,-2.956e-4,3.393695767766752e-11,3.3452143996557983e-10,34.0,
- * "2011-07-02T00:00:00Z",55744.0,2.193297093339541e-7,2.115460256837405e-6,-0.29065,-1.824e-4,-8.241832578862112e-11,5.623838700870617e-10,34.0,
- * "2011-07-03T00:00:00Z",55745.0,2.262286080161428e-7,2.1191157519929706e-6,-0.2905572,1.9e-6,-3.490658503988659e-10,6.981317007977318e-10,34.0
- * ]
- * }
- *
- * @example
- * // Loading the EOP data
- * var eop = new Cesium.EarthOrientationParameters({ url : 'Data/EOP.json' });
- * Cesium.Transforms.earthOrientationParameters = eop;
- *
- * @private
- */
- function EarthOrientationParameters(options) {
- options = when.defaultValue(options, when.defaultValue.EMPTY_OBJECT);
- this._dates = undefined;
- this._samples = undefined;
- this._dateColumn = -1;
- this._xPoleWanderRadiansColumn = -1;
- this._yPoleWanderRadiansColumn = -1;
- this._ut1MinusUtcSecondsColumn = -1;
- this._xCelestialPoleOffsetRadiansColumn = -1;
- this._yCelestialPoleOffsetRadiansColumn = -1;
- this._taiMinusUtcSecondsColumn = -1;
- this._columnCount = 0;
- this._lastIndex = -1;
- this._downloadPromise = undefined;
- this._dataError = undefined;
- this._addNewLeapSeconds = when.defaultValue(options.addNewLeapSeconds, true);
- if (when.defined(options.data)) {
- // Use supplied EOP data.
- onDataReady(this, options.data);
- } else if (when.defined(options.url)) {
- var resource = Resource.createIfNeeded(options.url);
- // Download EOP data.
- var that = this;
- this._downloadPromise = resource
- .fetchJson()
- .then(function (eopData) {
- onDataReady(that, eopData);
- })
- .otherwise(function () {
- that._dataError =
- "An error occurred while retrieving the EOP data from the URL " +
- resource.url +
- ".";
- });
- } else {
- // Use all zeros for EOP data.
- onDataReady(this, {
- columnNames: [
- "dateIso8601",
- "modifiedJulianDateUtc",
- "xPoleWanderRadians",
- "yPoleWanderRadians",
- "ut1MinusUtcSeconds",
- "lengthOfDayCorrectionSeconds",
- "xCelestialPoleOffsetRadians",
- "yCelestialPoleOffsetRadians",
- "taiMinusUtcSeconds",
- ],
- samples: [],
- });
- }
- }
- /**
- * A default {@link EarthOrientationParameters} instance that returns zero for all EOP values.
- */
- EarthOrientationParameters.NONE = Object.freeze({
- getPromiseToLoad: function () {
- return when.when.resolve();
- },
- compute: function (date, result) {
- if (!when.defined(result)) {
- result = new EarthOrientationParametersSample(0.0, 0.0, 0.0, 0.0, 0.0);
- } else {
- result.xPoleWander = 0.0;
- result.yPoleWander = 0.0;
- result.xPoleOffset = 0.0;
- result.yPoleOffset = 0.0;
- result.ut1MinusUtc = 0.0;
- }
- return result;
- },
- });
- /**
- * Gets a promise that, when resolved, indicates that the EOP data has been loaded and is
- * ready to use.
- *
- * @returns {Promise<void>} The promise.
- */
- EarthOrientationParameters.prototype.getPromiseToLoad = function () {
- return when.when(this._downloadPromise);
- };
- /**
- * Computes the Earth Orientation Parameters (EOP) for a given date by interpolating.
- * If the EOP data has not yet been download, this method returns undefined.
- *
- * @param {JulianDate} date The date for each to evaluate the EOP.
- * @param {EarthOrientationParametersSample} [result] The instance to which to copy the result.
- * If this parameter is undefined, a new instance is created and returned.
- * @returns {EarthOrientationParametersSample} The EOP evaluated at the given date, or
- * undefined if the data necessary to evaluate EOP at the date has not yet been
- * downloaded.
- *
- * @exception {RuntimeError} The loaded EOP data has an error and cannot be used.
- *
- * @see EarthOrientationParameters#getPromiseToLoad
- */
- EarthOrientationParameters.prototype.compute = function (date, result) {
- // We cannot compute until the samples are available.
- if (!when.defined(this._samples)) {
- if (when.defined(this._dataError)) {
- throw new RuntimeError.RuntimeError(this._dataError);
- }
- return undefined;
- }
- if (!when.defined(result)) {
- result = new EarthOrientationParametersSample(0.0, 0.0, 0.0, 0.0, 0.0);
- }
- if (this._samples.length === 0) {
- result.xPoleWander = 0.0;
- result.yPoleWander = 0.0;
- result.xPoleOffset = 0.0;
- result.yPoleOffset = 0.0;
- result.ut1MinusUtc = 0.0;
- return result;
- }
- var dates = this._dates;
- var lastIndex = this._lastIndex;
- var before = 0;
- var after = 0;
- if (when.defined(lastIndex)) {
- var previousIndexDate = dates[lastIndex];
- var nextIndexDate = dates[lastIndex + 1];
- var isAfterPrevious = JulianDate.lessThanOrEquals(previousIndexDate, date);
- var isAfterLastSample = !when.defined(nextIndexDate);
- var isBeforeNext =
- isAfterLastSample || JulianDate.greaterThanOrEquals(nextIndexDate, date);
- if (isAfterPrevious && isBeforeNext) {
- before = lastIndex;
- if (!isAfterLastSample && nextIndexDate.equals(date)) {
- ++before;
- }
- after = before + 1;
- interpolate(this, dates, this._samples, date, before, after, result);
- return result;
- }
- }
- var index = binarySearch(dates, date, JulianDate.compare, this._dateColumn);
- if (index >= 0) {
- // If the next entry is the same date, use the later entry. This way, if two entries
- // describe the same moment, one before a leap second and the other after, then we will use
- // the post-leap second data.
- if (index < dates.length - 1 && dates[index + 1].equals(date)) {
- ++index;
- }
- before = index;
- after = index;
- } else {
- after = ~index;
- before = after - 1;
- // Use the first entry if the date requested is before the beginning of the data.
- if (before < 0) {
- before = 0;
- }
- }
- this._lastIndex = before;
- interpolate(this, dates, this._samples, date, before, after, result);
- return result;
- };
- function compareLeapSecondDates$1(leapSecond, dateToFind) {
- return JulianDate.compare(leapSecond.julianDate, dateToFind);
- }
- function onDataReady(eop, eopData) {
- if (!when.defined(eopData.columnNames)) {
- eop._dataError =
- "Error in loaded EOP data: The columnNames property is required.";
- return;
- }
- if (!when.defined(eopData.samples)) {
- eop._dataError =
- "Error in loaded EOP data: The samples property is required.";
- return;
- }
- var dateColumn = eopData.columnNames.indexOf("modifiedJulianDateUtc");
- var xPoleWanderRadiansColumn = eopData.columnNames.indexOf(
- "xPoleWanderRadians"
- );
- var yPoleWanderRadiansColumn = eopData.columnNames.indexOf(
- "yPoleWanderRadians"
- );
- var ut1MinusUtcSecondsColumn = eopData.columnNames.indexOf(
- "ut1MinusUtcSeconds"
- );
- var xCelestialPoleOffsetRadiansColumn = eopData.columnNames.indexOf(
- "xCelestialPoleOffsetRadians"
- );
- var yCelestialPoleOffsetRadiansColumn = eopData.columnNames.indexOf(
- "yCelestialPoleOffsetRadians"
- );
- var taiMinusUtcSecondsColumn = eopData.columnNames.indexOf(
- "taiMinusUtcSeconds"
- );
- if (
- dateColumn < 0 ||
- xPoleWanderRadiansColumn < 0 ||
- yPoleWanderRadiansColumn < 0 ||
- ut1MinusUtcSecondsColumn < 0 ||
- xCelestialPoleOffsetRadiansColumn < 0 ||
- yCelestialPoleOffsetRadiansColumn < 0 ||
- taiMinusUtcSecondsColumn < 0
- ) {
- eop._dataError =
- "Error in loaded EOP data: The columnNames property must include modifiedJulianDateUtc, xPoleWanderRadians, yPoleWanderRadians, ut1MinusUtcSeconds, xCelestialPoleOffsetRadians, yCelestialPoleOffsetRadians, and taiMinusUtcSeconds columns";
- return;
- }
- var samples = (eop._samples = eopData.samples);
- var dates = (eop._dates = []);
- eop._dateColumn = dateColumn;
- eop._xPoleWanderRadiansColumn = xPoleWanderRadiansColumn;
- eop._yPoleWanderRadiansColumn = yPoleWanderRadiansColumn;
- eop._ut1MinusUtcSecondsColumn = ut1MinusUtcSecondsColumn;
- eop._xCelestialPoleOffsetRadiansColumn = xCelestialPoleOffsetRadiansColumn;
- eop._yCelestialPoleOffsetRadiansColumn = yCelestialPoleOffsetRadiansColumn;
- eop._taiMinusUtcSecondsColumn = taiMinusUtcSecondsColumn;
- eop._columnCount = eopData.columnNames.length;
- eop._lastIndex = undefined;
- var lastTaiMinusUtc;
- var addNewLeapSeconds = eop._addNewLeapSeconds;
- // Convert the ISO8601 dates to JulianDates.
- for (var i = 0, len = samples.length; i < len; i += eop._columnCount) {
- var mjd = samples[i + dateColumn];
- var taiMinusUtc = samples[i + taiMinusUtcSecondsColumn];
- var day = mjd + TimeConstants$1.MODIFIED_JULIAN_DATE_DIFFERENCE;
- var date = new JulianDate(day, taiMinusUtc, TimeStandard$1.TAI);
- dates.push(date);
- if (addNewLeapSeconds) {
- if (taiMinusUtc !== lastTaiMinusUtc && when.defined(lastTaiMinusUtc)) {
- // We crossed a leap second boundary, so add the leap second
- // if it does not already exist.
- var leapSeconds = JulianDate.leapSeconds;
- var leapSecondIndex = binarySearch(
- leapSeconds,
- date,
- compareLeapSecondDates$1
- );
- if (leapSecondIndex < 0) {
- var leapSecond = new LeapSecond(date, taiMinusUtc);
- leapSeconds.splice(~leapSecondIndex, 0, leapSecond);
- }
- }
- lastTaiMinusUtc = taiMinusUtc;
- }
- }
- }
- function fillResultFromIndex(eop, samples, index, columnCount, result) {
- var start = index * columnCount;
- result.xPoleWander = samples[start + eop._xPoleWanderRadiansColumn];
- result.yPoleWander = samples[start + eop._yPoleWanderRadiansColumn];
- result.xPoleOffset = samples[start + eop._xCelestialPoleOffsetRadiansColumn];
- result.yPoleOffset = samples[start + eop._yCelestialPoleOffsetRadiansColumn];
- result.ut1MinusUtc = samples[start + eop._ut1MinusUtcSecondsColumn];
- }
- function linearInterp(dx, y1, y2) {
- return y1 + dx * (y2 - y1);
- }
- function interpolate(eop, dates, samples, date, before, after, result) {
- var columnCount = eop._columnCount;
- // First check the bounds on the EOP data
- // If we are after the bounds of the data, return zeros.
- // The 'before' index should never be less than zero.
- if (after > dates.length - 1) {
- result.xPoleWander = 0;
- result.yPoleWander = 0;
- result.xPoleOffset = 0;
- result.yPoleOffset = 0;
- result.ut1MinusUtc = 0;
- return result;
- }
- var beforeDate = dates[before];
- var afterDate = dates[after];
- if (beforeDate.equals(afterDate) || date.equals(beforeDate)) {
- fillResultFromIndex(eop, samples, before, columnCount, result);
- return result;
- } else if (date.equals(afterDate)) {
- fillResultFromIndex(eop, samples, after, columnCount, result);
- return result;
- }
- var factor =
- JulianDate.secondsDifference(date, beforeDate) /
- JulianDate.secondsDifference(afterDate, beforeDate);
- var startBefore = before * columnCount;
- var startAfter = after * columnCount;
- // Handle UT1 leap second edge case
- var beforeUt1MinusUtc = samples[startBefore + eop._ut1MinusUtcSecondsColumn];
- var afterUt1MinusUtc = samples[startAfter + eop._ut1MinusUtcSecondsColumn];
- var offsetDifference = afterUt1MinusUtc - beforeUt1MinusUtc;
- if (offsetDifference > 0.5 || offsetDifference < -0.5) {
- // The absolute difference between the values is more than 0.5, so we may have
- // crossed a leap second. Check if this is the case and, if so, adjust the
- // afterValue to account for the leap second. This way, our interpolation will
- // produce reasonable results.
- var beforeTaiMinusUtc =
- samples[startBefore + eop._taiMinusUtcSecondsColumn];
- var afterTaiMinusUtc = samples[startAfter + eop._taiMinusUtcSecondsColumn];
- if (beforeTaiMinusUtc !== afterTaiMinusUtc) {
- if (afterDate.equals(date)) {
- // If we are at the end of the leap second interval, take the second value
- // Otherwise, the interpolation below will yield the wrong side of the
- // discontinuity
- // At the end of the leap second, we need to start accounting for the jump
- beforeUt1MinusUtc = afterUt1MinusUtc;
- } else {
- // Otherwise, remove the leap second so that the interpolation is correct
- afterUt1MinusUtc -= afterTaiMinusUtc - beforeTaiMinusUtc;
- }
- }
- }
- result.xPoleWander = linearInterp(
- factor,
- samples[startBefore + eop._xPoleWanderRadiansColumn],
- samples[startAfter + eop._xPoleWanderRadiansColumn]
- );
- result.yPoleWander = linearInterp(
- factor,
- samples[startBefore + eop._yPoleWanderRadiansColumn],
- samples[startAfter + eop._yPoleWanderRadiansColumn]
- );
- result.xPoleOffset = linearInterp(
- factor,
- samples[startBefore + eop._xCelestialPoleOffsetRadiansColumn],
- samples[startAfter + eop._xCelestialPoleOffsetRadiansColumn]
- );
- result.yPoleOffset = linearInterp(
- factor,
- samples[startBefore + eop._yCelestialPoleOffsetRadiansColumn],
- samples[startAfter + eop._yCelestialPoleOffsetRadiansColumn]
- );
- result.ut1MinusUtc = linearInterp(
- factor,
- beforeUt1MinusUtc,
- afterUt1MinusUtc
- );
- return result;
- }
- /**
- * A rotation expressed as a heading, pitch, and roll. Heading is the rotation about the
- * negative z axis. Pitch is the rotation about the negative y axis. Roll is the rotation about
- * the positive x axis.
- * @alias HeadingPitchRoll
- * @constructor
- *
- * @param {Number} [heading=0.0] The heading component in radians.
- * @param {Number} [pitch=0.0] The pitch component in radians.
- * @param {Number} [roll=0.0] The roll component in radians.
- */
- function HeadingPitchRoll(heading, pitch, roll) {
- /**
- * Gets or sets the heading.
- * @type {Number}
- * @default 0.0
- */
- this.heading = when.defaultValue(heading, 0.0);
- /**
- * Gets or sets the pitch.
- * @type {Number}
- * @default 0.0
- */
- this.pitch = when.defaultValue(pitch, 0.0);
- /**
- * Gets or sets the roll.
- * @type {Number}
- * @default 0.0
- */
- this.roll = when.defaultValue(roll, 0.0);
- }
- /**
- * Computes the heading, pitch and roll from a quaternion (see http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles )
- *
- * @param {Quaternion} quaternion The quaternion from which to retrieve heading, pitch, and roll, all expressed in radians.
- * @param {HeadingPitchRoll} [result] The object in which to store the result. If not provided, a new instance is created and returned.
- * @returns {HeadingPitchRoll} The modified result parameter or a new HeadingPitchRoll instance if one was not provided.
- */
- HeadingPitchRoll.fromQuaternion = function (quaternion, result) {
- //>>includeStart('debug', pragmas.debug);
- if (!when.defined(quaternion)) {
- throw new Check.DeveloperError("quaternion is required");
- }
- //>>includeEnd('debug');
- if (!when.defined(result)) {
- result = new HeadingPitchRoll();
- }
- var test = 2 * (quaternion.w * quaternion.y - quaternion.z * quaternion.x);
- var denominatorRoll =
- 1 - 2 * (quaternion.x * quaternion.x + quaternion.y * quaternion.y);
- var numeratorRoll =
- 2 * (quaternion.w * quaternion.x + quaternion.y * quaternion.z);
- var denominatorHeading =
- 1 - 2 * (quaternion.y * quaternion.y + quaternion.z * quaternion.z);
- var numeratorHeading =
- 2 * (quaternion.w * quaternion.z + quaternion.x * quaternion.y);
- result.heading = -Math.atan2(numeratorHeading, denominatorHeading);
- result.roll = Math.atan2(numeratorRoll, denominatorRoll);
- result.pitch = -_Math.CesiumMath.asinClamped(test);
- return result;
- };
- /**
- * Returns a new HeadingPitchRoll instance from angles given in degrees.
- *
- * @param {Number} heading the heading in degrees
- * @param {Number} pitch the pitch in degrees
- * @param {Number} roll the heading in degrees
- * @param {HeadingPitchRoll} [result] The object in which to store the result. If not provided, a new instance is created and returned.
- * @returns {HeadingPitchRoll} A new HeadingPitchRoll instance
- */
- HeadingPitchRoll.fromDegrees = function (heading, pitch, roll, result) {
- //>>includeStart('debug', pragmas.debug);
- if (!when.defined(heading)) {
- throw new Check.DeveloperError("heading is required");
- }
- if (!when.defined(pitch)) {
- throw new Check.DeveloperError("pitch is required");
- }
- if (!when.defined(roll)) {
- throw new Check.DeveloperError("roll is required");
- }
- //>>includeEnd('debug');
- if (!when.defined(result)) {
- result = new HeadingPitchRoll();
- }
- result.heading = heading * _Math.CesiumMath.RADIANS_PER_DEGREE;
- result.pitch = pitch * _Math.CesiumMath.RADIANS_PER_DEGREE;
- result.roll = roll * _Math.CesiumMath.RADIANS_PER_DEGREE;
- return result;
- };
- /**
- * Duplicates a HeadingPitchRoll instance.
- *
- * @param {HeadingPitchRoll} headingPitchRoll The HeadingPitchRoll to duplicate.
- * @param {HeadingPitchRoll} [result] The object onto which to store the result.
- * @returns {HeadingPitchRoll} The modified result parameter or a new HeadingPitchRoll instance if one was not provided. (Returns undefined if headingPitchRoll is undefined)
- */
- HeadingPitchRoll.clone = function (headingPitchRoll, result) {
- if (!when.defined(headingPitchRoll)) {
- return undefined;
- }
- if (!when.defined(result)) {
- return new HeadingPitchRoll(
- headingPitchRoll.heading,
- headingPitchRoll.pitch,
- headingPitchRoll.roll
- );
- }
- result.heading = headingPitchRoll.heading;
- result.pitch = headingPitchRoll.pitch;
- result.roll = headingPitchRoll.roll;
- return result;
- };
- /**
- * Compares the provided HeadingPitchRolls componentwise and returns
- * <code>true</code> if they are equal, <code>false</code> otherwise.
- *
- * @param {HeadingPitchRoll} [left] The first HeadingPitchRoll.
- * @param {HeadingPitchRoll} [right] The second HeadingPitchRoll.
- * @returns {Boolean} <code>true</code> if left and right are equal, <code>false</code> otherwise.
- */
- HeadingPitchRoll.equals = function (left, right) {
- return (
- left === right ||
- (when.defined(left) &&
- when.defined(right) &&
- left.heading === right.heading &&
- left.pitch === right.pitch &&
- left.roll === right.roll)
- );
- };
- /**
- * Compares the provided HeadingPitchRolls componentwise and returns
- * <code>true</code> if they pass an absolute or relative tolerance test,
- * <code>false</code> otherwise.
- *
- * @param {HeadingPitchRoll} [left] The first HeadingPitchRoll.
- * @param {HeadingPitchRoll} [right] The second HeadingPitchRoll.
- * @param {Number} [relativeEpsilon=0] The relative epsilon tolerance to use for equality testing.
- * @param {Number} [absoluteEpsilon=relativeEpsilon] The absolute epsilon tolerance to use for equality testing.
- * @returns {Boolean} <code>true</code> if left and right are within the provided epsilon, <code>false</code> otherwise.
- */
- HeadingPitchRoll.equalsEpsilon = function (
- left,
- right,
- relativeEpsilon,
- absoluteEpsilon
- ) {
- return (
- left === right ||
- (when.defined(left) &&
- when.defined(right) &&
- _Math.CesiumMath.equalsEpsilon(
- left.heading,
- right.heading,
- relativeEpsilon,
- absoluteEpsilon
- ) &&
- _Math.CesiumMath.equalsEpsilon(
- left.pitch,
- right.pitch,
- relativeEpsilon,
- absoluteEpsilon
- ) &&
- _Math.CesiumMath.equalsEpsilon(
- left.roll,
- right.roll,
- relativeEpsilon,
- absoluteEpsilon
- ))
- );
- };
- /**
- * Duplicates this HeadingPitchRoll instance.
- *
- * @param {HeadingPitchRoll} [result] The object onto which to store the result.
- * @returns {HeadingPitchRoll} The modified result parameter or a new HeadingPitchRoll instance if one was not provided.
- */
- HeadingPitchRoll.prototype.clone = function (result) {
- return HeadingPitchRoll.clone(this, result);
- };
- /**
- * Compares this HeadingPitchRoll against the provided HeadingPitchRoll componentwise and returns
- * <code>true</code> if they are equal, <code>false</code> otherwise.
- *
- * @param {HeadingPitchRoll} [right] The right hand side HeadingPitchRoll.
- * @returns {Boolean} <code>true</code> if they are equal, <code>false</code> otherwise.
- */
- HeadingPitchRoll.prototype.equals = function (right) {
- return HeadingPitchRoll.equals(this, right);
- };
- /**
- * Compares this HeadingPitchRoll against the provided HeadingPitchRoll componentwise and returns
- * <code>true</code> if they pass an absolute or relative tolerance test,
- * <code>false</code> otherwise.
- *
- * @param {HeadingPitchRoll} [right] The right hand side HeadingPitchRoll.
- * @param {Number} [relativeEpsilon=0] The relative epsilon tolerance to use for equality testing.
- * @param {Number} [absoluteEpsilon=relativeEpsilon] The absolute epsilon tolerance to use for equality testing.
- * @returns {Boolean} <code>true</code> if they are within the provided epsilon, <code>false</code> otherwise.
- */
- HeadingPitchRoll.prototype.equalsEpsilon = function (
- right,
- relativeEpsilon,
- absoluteEpsilon
- ) {
- return HeadingPitchRoll.equalsEpsilon(
- this,
- right,
- relativeEpsilon,
- absoluteEpsilon
- );
- };
- /**
- * Creates a string representing this HeadingPitchRoll in the format '(heading, pitch, roll)' in radians.
- *
- * @returns {String} A string representing the provided HeadingPitchRoll in the format '(heading, pitch, roll)'.
- */
- HeadingPitchRoll.prototype.toString = function () {
- return "(" + this.heading + ", " + this.pitch + ", " + this.roll + ")";
- };
- /*global CESIUM_BASE_URL*/
- var cesiumScriptRegex = /((?:.*\/)|^)Cesium\.js(?:\?|\#|$)/;
- function getBaseUrlFromCesiumScript() {
- var scripts = document.getElementsByTagName("script");
- for (var i = 0, len = scripts.length; i < len; ++i) {
- var src = scripts[i].getAttribute("src");
- var result = cesiumScriptRegex.exec(src);
- if (result !== null) {
- return result[1];
- }
- }
- return undefined;
- }
- var a$1;
- function tryMakeAbsolute(url) {
- if (typeof document === "undefined") {
- //Node.js and Web Workers. In both cases, the URL will already be absolute.
- return url;
- }
- if (!when.defined(a$1)) {
- a$1 = document.createElement("a");
- }
- a$1.href = url;
- // IE only absolutizes href on get, not set
- // eslint-disable-next-line no-self-assign
- a$1.href = a$1.href;
- return a$1.href;
- }
- var baseResource;
- function getCesiumBaseUrl() {
- if (when.defined(baseResource)) {
- return baseResource;
- }
- var baseUrlString;
- if (typeof CESIUM_BASE_URL !== "undefined") {
- baseUrlString = CESIUM_BASE_URL;
- } else if (
- typeof define === "object" &&
- when.defined(define.amd) &&
- !define.amd.toUrlUndefined &&
- when.defined(require.toUrl)
- ) {
- baseUrlString = getAbsoluteUri(
- "..",
- buildModuleUrl("Core/buildModuleUrl.js")
- );
- } else {
- baseUrlString = getBaseUrlFromCesiumScript();
- }
- //>>includeStart('debug', pragmas.debug);
- if (!when.defined(baseUrlString)) {
- throw new Check.DeveloperError(
- "Unable to determine Cesium base URL automatically, try defining a global variable called CESIUM_BASE_URL."
- );
- }
- //>>includeEnd('debug');
- baseResource = new Resource({
- url: tryMakeAbsolute(baseUrlString),
- });
- baseResource.appendForwardSlash();
- return baseResource;
- }
- function buildModuleUrlFromRequireToUrl(moduleID) {
- //moduleID will be non-relative, so require it relative to this module, in Core.
- return tryMakeAbsolute(require.toUrl("../" + moduleID));
- }
- function buildModuleUrlFromBaseUrl(moduleID) {
- var resource = getCesiumBaseUrl().getDerivedResource({
- url: moduleID,
- });
- return resource.url;
- }
- var implementation;
- /**
- * Given a relative URL under the Cesium base URL, returns an absolute URL.
- * @function
- *
- * @param {String} relativeUrl The relative path.
- * @returns {String} The absolutely URL representation of the provided path.
- *
- * @example
- * var viewer = new Cesium.Viewer("cesiumContainer", {
- * imageryProvider: new Cesium.TileMapServiceImageryProvider({
- * url: Cesium.buildModuleUrl("Assets/Textures/NaturalEarthII"),
- * }),
- * baseLayerPicker: false,
- * });
- */
- function buildModuleUrl(relativeUrl) {
- if (!when.defined(implementation)) {
- //select implementation
- if (
- typeof define === "object" &&
- when.defined(define.amd) &&
- !define.amd.toUrlUndefined &&
- when.defined(require.toUrl)
- ) {
- implementation = buildModuleUrlFromRequireToUrl;
- } else {
- implementation = buildModuleUrlFromBaseUrl;
- }
- }
- var url = implementation(relativeUrl);
- return url;
- }
- // exposed for testing
- buildModuleUrl._cesiumScriptRegex = cesiumScriptRegex;
- buildModuleUrl._buildModuleUrlFromBaseUrl = buildModuleUrlFromBaseUrl;
- buildModuleUrl._clearBaseResource = function () {
- baseResource = undefined;
- };
- /**
- * Sets the base URL for resolving modules.
- * @param {String} value The new base URL.
- */
- buildModuleUrl.setBaseUrl = function (value) {
- baseResource = Resource.DEFAULT.getDerivedResource({
- url: value,
- });
- };
- /**
- * Gets the base URL for resolving modules.
- */
- buildModuleUrl.getCesiumBaseUrl = getCesiumBaseUrl;
- /**
- * An IAU 2006 XYS value sampled at a particular time.
- *
- * @alias Iau2006XysSample
- * @constructor
- *
- * @param {Number} x The X value.
- * @param {Number} y The Y value.
- * @param {Number} s The S value.
- *
- * @private
- */
- function Iau2006XysSample(x, y, s) {
- /**
- * The X value.
- * @type {Number}
- */
- this.x = x;
- /**
- * The Y value.
- * @type {Number}
- */
- this.y = y;
- /**
- * The S value.
- * @type {Number}
- */
- this.s = s;
- }
- /**
- * A set of IAU2006 XYS data that is used to evaluate the transformation between the International
- * Celestial Reference Frame (ICRF) and the International Terrestrial Reference Frame (ITRF).
- *
- * @alias Iau2006XysData
- * @constructor
- *
- * @param {Object} [options] Object with the following properties:
- * @param {Resource|String} [options.xysFileUrlTemplate='Assets/IAU2006_XYS/IAU2006_XYS_{0}.json'] A template URL for obtaining the XYS data. In the template,
- * `{0}` will be replaced with the file index.
- * @param {Number} [options.interpolationOrder=9] The order of interpolation to perform on the XYS data.
- * @param {Number} [options.sampleZeroJulianEphemerisDate=2442396.5] The Julian ephemeris date (JED) of the
- * first XYS sample.
- * @param {Number} [options.stepSizeDays=1.0] The step size, in days, between successive XYS samples.
- * @param {Number} [options.samplesPerXysFile=1000] The number of samples in each XYS file.
- * @param {Number} [options.totalSamples=27426] The total number of samples in all XYS files.
- *
- * @private
- */
- function Iau2006XysData(options) {
- options = when.defaultValue(options, when.defaultValue.EMPTY_OBJECT);
- this._xysFileUrlTemplate = Resource.createIfNeeded(
- options.xysFileUrlTemplate
- );
- this._interpolationOrder = when.defaultValue(options.interpolationOrder, 9);
- this._sampleZeroJulianEphemerisDate = when.defaultValue(
- options.sampleZeroJulianEphemerisDate,
- 2442396.5
- );
- this._sampleZeroDateTT = new JulianDate(
- this._sampleZeroJulianEphemerisDate,
- 0.0,
- TimeStandard$1.TAI
- );
- this._stepSizeDays = when.defaultValue(options.stepSizeDays, 1.0);
- this._samplesPerXysFile = when.defaultValue(options.samplesPerXysFile, 1000);
- this._totalSamples = when.defaultValue(options.totalSamples, 27426);
- this._samples = new Array(this._totalSamples * 3);
- this._chunkDownloadsInProgress = [];
- var order = this._interpolationOrder;
- // Compute denominators and X values for interpolation.
- var denom = (this._denominators = new Array(order + 1));
- var xTable = (this._xTable = new Array(order + 1));
- var stepN = Math.pow(this._stepSizeDays, order);
- for (var i = 0; i <= order; ++i) {
- denom[i] = stepN;
- xTable[i] = i * this._stepSizeDays;
- for (var j = 0; j <= order; ++j) {
- if (j !== i) {
- denom[i] *= i - j;
- }
- }
- denom[i] = 1.0 / denom[i];
- }
- // Allocate scratch arrays for interpolation.
- this._work = new Array(order + 1);
- this._coef = new Array(order + 1);
- }
- var julianDateScratch = new JulianDate(0, 0.0, TimeStandard$1.TAI);
- function getDaysSinceEpoch(xys, dayTT, secondTT) {
- var dateTT = julianDateScratch;
- dateTT.dayNumber = dayTT;
- dateTT.secondsOfDay = secondTT;
- return JulianDate.daysDifference(dateTT, xys._sampleZeroDateTT);
- }
- /**
- * Preloads XYS data for a specified date range.
- *
- * @param {Number} startDayTT The Julian day number of the beginning of the interval to preload, expressed in
- * the Terrestrial Time (TT) time standard.
- * @param {Number} startSecondTT The seconds past noon of the beginning of the interval to preload, expressed in
- * the Terrestrial Time (TT) time standard.
- * @param {Number} stopDayTT The Julian day number of the end of the interval to preload, expressed in
- * the Terrestrial Time (TT) time standard.
- * @param {Number} stopSecondTT The seconds past noon of the end of the interval to preload, expressed in
- * the Terrestrial Time (TT) time standard.
- * @returns {Promise<void>} A promise that, when resolved, indicates that the requested interval has been
- * preloaded.
- */
- Iau2006XysData.prototype.preload = function (
- startDayTT,
- startSecondTT,
- stopDayTT,
- stopSecondTT
- ) {
- var startDaysSinceEpoch = getDaysSinceEpoch(this, startDayTT, startSecondTT);
- var stopDaysSinceEpoch = getDaysSinceEpoch(this, stopDayTT, stopSecondTT);
- var startIndex =
- (startDaysSinceEpoch / this._stepSizeDays - this._interpolationOrder / 2) |
- 0;
- if (startIndex < 0) {
- startIndex = 0;
- }
- var stopIndex =
- (stopDaysSinceEpoch / this._stepSizeDays - this._interpolationOrder / 2) |
- (0 + this._interpolationOrder);
- if (stopIndex >= this._totalSamples) {
- stopIndex = this._totalSamples - 1;
- }
- var startChunk = (startIndex / this._samplesPerXysFile) | 0;
- var stopChunk = (stopIndex / this._samplesPerXysFile) | 0;
- var promises = [];
- for (var i = startChunk; i <= stopChunk; ++i) {
- promises.push(requestXysChunk(this, i));
- }
- return when.when.all(promises);
- };
- /**
- * Computes the XYS values for a given date by interpolating. If the required data is not yet downloaded,
- * this method will return undefined.
- *
- * @param {Number} dayTT The Julian day number for which to compute the XYS value, expressed in
- * the Terrestrial Time (TT) time standard.
- * @param {Number} secondTT The seconds past noon of the date for which to compute the XYS value, expressed in
- * the Terrestrial Time (TT) time standard.
- * @param {Iau2006XysSample} [result] The instance to which to copy the interpolated result. If this parameter
- * is undefined, a new instance is allocated and returned.
- * @returns {Iau2006XysSample} The interpolated XYS values, or undefined if the required data for this
- * computation has not yet been downloaded.
- *
- * @see Iau2006XysData#preload
- */
- Iau2006XysData.prototype.computeXysRadians = function (
- dayTT,
- secondTT,
- result
- ) {
- var daysSinceEpoch = getDaysSinceEpoch(this, dayTT, secondTT);
- if (daysSinceEpoch < 0.0) {
- // Can't evaluate prior to the epoch of the data.
- return undefined;
- }
- var centerIndex = (daysSinceEpoch / this._stepSizeDays) | 0;
- if (centerIndex >= this._totalSamples) {
- // Can't evaluate after the last sample in the data.
- return undefined;
- }
- var degree = this._interpolationOrder;
- var firstIndex = centerIndex - ((degree / 2) | 0);
- if (firstIndex < 0) {
- firstIndex = 0;
- }
- var lastIndex = firstIndex + degree;
- if (lastIndex >= this._totalSamples) {
- lastIndex = this._totalSamples - 1;
- firstIndex = lastIndex - degree;
- if (firstIndex < 0) {
- firstIndex = 0;
- }
- }
- // Are all the samples we need present?
- // We can assume so if the first and last are present
- var isDataMissing = false;
- var samples = this._samples;
- if (!when.defined(samples[firstIndex * 3])) {
- requestXysChunk(this, (firstIndex / this._samplesPerXysFile) | 0);
- isDataMissing = true;
- }
- if (!when.defined(samples[lastIndex * 3])) {
- requestXysChunk(this, (lastIndex / this._samplesPerXysFile) | 0);
- isDataMissing = true;
- }
- if (isDataMissing) {
- return undefined;
- }
- if (!when.defined(result)) {
- result = new Iau2006XysSample(0.0, 0.0, 0.0);
- } else {
- result.x = 0.0;
- result.y = 0.0;
- result.s = 0.0;
- }
- var x = daysSinceEpoch - firstIndex * this._stepSizeDays;
- var work = this._work;
- var denom = this._denominators;
- var coef = this._coef;
- var xTable = this._xTable;
- var i, j;
- for (i = 0; i <= degree; ++i) {
- work[i] = x - xTable[i];
- }
- for (i = 0; i <= degree; ++i) {
- coef[i] = 1.0;
- for (j = 0; j <= degree; ++j) {
- if (j !== i) {
- coef[i] *= work[j];
- }
- }
- coef[i] *= denom[i];
- var sampleIndex = (firstIndex + i) * 3;
- result.x += coef[i] * samples[sampleIndex++];
- result.y += coef[i] * samples[sampleIndex++];
- result.s += coef[i] * samples[sampleIndex];
- }
- return result;
- };
- function requestXysChunk(xysData, chunkIndex) {
- if (xysData._chunkDownloadsInProgress[chunkIndex]) {
- // Chunk has already been requested.
- return xysData._chunkDownloadsInProgress[chunkIndex];
- }
- var deferred = when.when.defer();
- xysData._chunkDownloadsInProgress[chunkIndex] = deferred;
- var chunkUrl;
- var xysFileUrlTemplate = xysData._xysFileUrlTemplate;
- if (when.defined(xysFileUrlTemplate)) {
- chunkUrl = xysFileUrlTemplate.getDerivedResource({
- templateValues: {
- "0": chunkIndex,
- },
- });
- } else {
- chunkUrl = new Resource({
- url: buildModuleUrl(
- "Assets/IAU2006_XYS/IAU2006_XYS_" + chunkIndex + ".json"
- ),
- });
- }
- when.when(chunkUrl.fetchJson(), function (chunk) {
- xysData._chunkDownloadsInProgress[chunkIndex] = false;
- var samples = xysData._samples;
- var newSamples = chunk.samples;
- var startIndex = chunkIndex * xysData._samplesPerXysFile * 3;
- for (var i = 0, len = newSamples.length; i < len; ++i) {
- samples[startIndex + i] = newSamples[i];
- }
- deferred.resolve();
- });
- return deferred.promise;
- }
- /**
- * Contains functions for transforming positions to various reference frames.
- *
- * @namespace Transforms
- */
- var Transforms = {};
- var vectorProductLocalFrame = {
- up: {
- south: "east",
- north: "west",
- west: "south",
- east: "north",
- },
- down: {
- south: "west",
- north: "east",
- west: "north",
- east: "south",
- },
- south: {
- up: "west",
- down: "east",
- west: "down",
- east: "up",
- },
- north: {
- up: "east",
- down: "west",
- west: "up",
- east: "down",
- },
- west: {
- up: "north",
- down: "south",
- north: "down",
- south: "up",
- },
- east: {
- up: "south",
- down: "north",
- north: "up",
- south: "down",
- },
- };
- var degeneratePositionLocalFrame = {
- north: [-1, 0, 0],
- east: [0, 1, 0],
- up: [0, 0, 1],
- south: [1, 0, 0],
- west: [0, -1, 0],
- down: [0, 0, -1],
- };
- var localFrameToFixedFrameCache = {};
- var scratchCalculateCartesian = {
- east: new Cartesian2.Cartesian3(),
- north: new Cartesian2.Cartesian3(),
- up: new Cartesian2.Cartesian3(),
- west: new Cartesian2.Cartesian3(),
- south: new Cartesian2.Cartesian3(),
- down: new Cartesian2.Cartesian3(),
- };
- var scratchFirstCartesian = new Cartesian2.Cartesian3();
- var scratchSecondCartesian = new Cartesian2.Cartesian3();
- var scratchThirdCartesian = new Cartesian2.Cartesian3();
- /**
- * Generates a function that computes a 4x4 transformation matrix from a reference frame
- * centered at the provided origin to the provided ellipsoid's fixed reference frame.
- * @param {String} firstAxis name of the first axis of the local reference frame. Must be
- * 'east', 'north', 'up', 'west', 'south' or 'down'.
- * @param {String} secondAxis name of the second axis of the local reference frame. Must be
- * 'east', 'north', 'up', 'west', 'south' or 'down'.
- * @return {Transforms.LocalFrameToFixedFrame} The function that will computes a
- * 4x4 transformation matrix from a reference frame, with first axis and second axis compliant with the parameters,
- */
- Transforms.localFrameToFixedFrameGenerator = function (firstAxis, secondAxis) {
- if (
- !vectorProductLocalFrame.hasOwnProperty(firstAxis) ||
- !vectorProductLocalFrame[firstAxis].hasOwnProperty(secondAxis)
- ) {
- throw new Check.DeveloperError(
- "firstAxis and secondAxis must be east, north, up, west, south or down."
- );
- }
- var thirdAxis = vectorProductLocalFrame[firstAxis][secondAxis];
- /**
- * Computes a 4x4 transformation matrix from a reference frame
- * centered at the provided origin to the provided ellipsoid's fixed reference frame.
- * @callback Transforms.LocalFrameToFixedFrame
- * @param {Cartesian3} origin The center point of the local reference frame.
- * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid whose fixed frame is used in the transformation.
- * @param {Matrix4} [result] The object onto which to store the result.
- * @returns {Matrix4} The modified result parameter or a new Matrix4 instance if none was provided.
- */
- var resultat;
- var hashAxis = firstAxis + secondAxis;
- if (when.defined(localFrameToFixedFrameCache[hashAxis])) {
- resultat = localFrameToFixedFrameCache[hashAxis];
- } else {
- resultat = function (origin, ellipsoid, result) {
- //>>includeStart('debug', pragmas.debug);
- if (!when.defined(origin)) {
- throw new Check.DeveloperError("origin is required.");
- }
- //>>includeEnd('debug');
- if (!when.defined(result)) {
- result = new Matrix4();
- }
- if (
- Cartesian2.Cartesian3.equalsEpsilon(origin, Cartesian2.Cartesian3.ZERO, _Math.CesiumMath.EPSILON14)
- ) {
- // If x, y, and z are zero, use the degenerate local frame, which is a special case
- Cartesian2.Cartesian3.unpack(
- degeneratePositionLocalFrame[firstAxis],
- 0,
- scratchFirstCartesian
- );
- Cartesian2.Cartesian3.unpack(
- degeneratePositionLocalFrame[secondAxis],
- 0,
- scratchSecondCartesian
- );
- Cartesian2.Cartesian3.unpack(
- degeneratePositionLocalFrame[thirdAxis],
- 0,
- scratchThirdCartesian
- );
- } else if (
- _Math.CesiumMath.equalsEpsilon(origin.x, 0.0, _Math.CesiumMath.EPSILON14) &&
- _Math.CesiumMath.equalsEpsilon(origin.y, 0.0, _Math.CesiumMath.EPSILON14)
- ) {
- // If x and y are zero, assume origin is at a pole, which is a special case.
- var sign = _Math.CesiumMath.sign(origin.z);
- Cartesian2.Cartesian3.unpack(
- degeneratePositionLocalFrame[firstAxis],
- 0,
- scratchFirstCartesian
- );
- if (firstAxis !== "east" && firstAxis !== "west") {
- Cartesian2.Cartesian3.multiplyByScalar(
- scratchFirstCartesian,
- sign,
- scratchFirstCartesian
- );
- }
- Cartesian2.Cartesian3.unpack(
- degeneratePositionLocalFrame[secondAxis],
- 0,
- scratchSecondCartesian
- );
- if (secondAxis !== "east" && secondAxis !== "west") {
- Cartesian2.Cartesian3.multiplyByScalar(
- scratchSecondCartesian,
- sign,
- scratchSecondCartesian
- );
- }
- Cartesian2.Cartesian3.unpack(
- degeneratePositionLocalFrame[thirdAxis],
- 0,
- scratchThirdCartesian
- );
- if (thirdAxis !== "east" && thirdAxis !== "west") {
- Cartesian2.Cartesian3.multiplyByScalar(
- scratchThirdCartesian,
- sign,
- scratchThirdCartesian
- );
- }
- } else {
- ellipsoid = when.defaultValue(ellipsoid, Cartesian2.Ellipsoid.WGS84);
- ellipsoid.geodeticSurfaceNormal(origin, scratchCalculateCartesian.up);
- var up = scratchCalculateCartesian.up;
- var east = scratchCalculateCartesian.east;
- east.x = -origin.y;
- east.y = origin.x;
- east.z = 0.0;
- Cartesian2.Cartesian3.normalize(east, scratchCalculateCartesian.east);
- Cartesian2.Cartesian3.cross(up, east, scratchCalculateCartesian.north);
- Cartesian2.Cartesian3.multiplyByScalar(
- scratchCalculateCartesian.up,
- -1,
- scratchCalculateCartesian.down
- );
- Cartesian2.Cartesian3.multiplyByScalar(
- scratchCalculateCartesian.east,
- -1,
- scratchCalculateCartesian.west
- );
- Cartesian2.Cartesian3.multiplyByScalar(
- scratchCalculateCartesian.north,
- -1,
- scratchCalculateCartesian.south
- );
- scratchFirstCartesian = scratchCalculateCartesian[firstAxis];
- scratchSecondCartesian = scratchCalculateCartesian[secondAxis];
- scratchThirdCartesian = scratchCalculateCartesian[thirdAxis];
- }
- result[0] = scratchFirstCartesian.x;
- result[1] = scratchFirstCartesian.y;
- result[2] = scratchFirstCartesian.z;
- result[3] = 0.0;
- result[4] = scratchSecondCartesian.x;
- result[5] = scratchSecondCartesian.y;
- result[6] = scratchSecondCartesian.z;
- result[7] = 0.0;
- result[8] = scratchThirdCartesian.x;
- result[9] = scratchThirdCartesian.y;
- result[10] = scratchThirdCartesian.z;
- result[11] = 0.0;
- result[12] = origin.x;
- result[13] = origin.y;
- result[14] = origin.z;
- result[15] = 1.0;
- return result;
- };
- localFrameToFixedFrameCache[hashAxis] = resultat;
- }
- return resultat;
- };
- /**
- * Computes a 4x4 transformation matrix from a reference frame with an east-north-up axes
- * centered at the provided origin to the provided ellipsoid's fixed reference frame.
- * The local axes are defined as:
- * <ul>
- * <li>The <code>x</code> axis points in the local east direction.</li>
- * <li>The <code>y</code> axis points in the local north direction.</li>
- * <li>The <code>z</code> axis points in the direction of the ellipsoid surface normal which passes through the position.</li>
- * </ul>
- *
- * @function
- * @param {Cartesian3} origin The center point of the local reference frame.
- * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid whose fixed frame is used in the transformation.
- * @param {Matrix4} [result] The object onto which to store the result.
- * @returns {Matrix4} The modified result parameter or a new Matrix4 instance if none was provided.
- *
- * @example
- * // Get the transform from local east-north-up at cartographic (0.0, 0.0) to Earth's fixed frame.
- * var center = Cesium.Cartesian3.fromDegrees(0.0, 0.0);
- * var transform = Cesium.Transforms.eastNorthUpToFixedFrame(center);
- */
- Transforms.eastNorthUpToFixedFrame = Transforms.localFrameToFixedFrameGenerator(
- "east",
- "north"
- );
- /**
- * Computes a 4x4 transformation matrix from a reference frame with an north-east-down axes
- * centered at the provided origin to the provided ellipsoid's fixed reference frame.
- * The local axes are defined as:
- * <ul>
- * <li>The <code>x</code> axis points in the local north direction.</li>
- * <li>The <code>y</code> axis points in the local east direction.</li>
- * <li>The <code>z</code> axis points in the opposite direction of the ellipsoid surface normal which passes through the position.</li>
- * </ul>
- *
- * @function
- * @param {Cartesian3} origin The center point of the local reference frame.
- * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid whose fixed frame is used in the transformation.
- * @param {Matrix4} [result] The object onto which to store the result.
- * @returns {Matrix4} The modified result parameter or a new Matrix4 instance if none was provided.
- *
- * @example
- * // Get the transform from local north-east-down at cartographic (0.0, 0.0) to Earth's fixed frame.
- * var center = Cesium.Cartesian3.fromDegrees(0.0, 0.0);
- * var transform = Cesium.Transforms.northEastDownToFixedFrame(center);
- */
- Transforms.northEastDownToFixedFrame = Transforms.localFrameToFixedFrameGenerator(
- "north",
- "east"
- );
- /**
- * Computes a 4x4 transformation matrix from a reference frame with an north-up-east axes
- * centered at the provided origin to the provided ellipsoid's fixed reference frame.
- * The local axes are defined as:
- * <ul>
- * <li>The <code>x</code> axis points in the local north direction.</li>
- * <li>The <code>y</code> axis points in the direction of the ellipsoid surface normal which passes through the position.</li>
- * <li>The <code>z</code> axis points in the local east direction.</li>
- * </ul>
- *
- * @function
- * @param {Cartesian3} origin The center point of the local reference frame.
- * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid whose fixed frame is used in the transformation.
- * @param {Matrix4} [result] The object onto which to store the result.
- * @returns {Matrix4} The modified result parameter or a new Matrix4 instance if none was provided.
- *
- * @example
- * // Get the transform from local north-up-east at cartographic (0.0, 0.0) to Earth's fixed frame.
- * var center = Cesium.Cartesian3.fromDegrees(0.0, 0.0);
- * var transform = Cesium.Transforms.northUpEastToFixedFrame(center);
- */
- Transforms.northUpEastToFixedFrame = Transforms.localFrameToFixedFrameGenerator(
- "north",
- "up"
- );
- /**
- * Computes a 4x4 transformation matrix from a reference frame with an north-west-up axes
- * centered at the provided origin to the provided ellipsoid's fixed reference frame.
- * The local axes are defined as:
- * <ul>
- * <li>The <code>x</code> axis points in the local north direction.</li>
- * <li>The <code>y</code> axis points in the local west direction.</li>
- * <li>The <code>z</code> axis points in the direction of the ellipsoid surface normal which passes through the position.</li>
- * </ul>
- *
- * @function
- * @param {Cartesian3} origin The center point of the local reference frame.
- * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid whose fixed frame is used in the transformation.
- * @param {Matrix4} [result] The object onto which to store the result.
- * @returns {Matrix4} The modified result parameter or a new Matrix4 instance if none was provided.
- *
- * @example
- * // Get the transform from local north-West-Up at cartographic (0.0, 0.0) to Earth's fixed frame.
- * var center = Cesium.Cartesian3.fromDegrees(0.0, 0.0);
- * var transform = Cesium.Transforms.northWestUpToFixedFrame(center);
- */
- Transforms.northWestUpToFixedFrame = Transforms.localFrameToFixedFrameGenerator(
- "north",
- "west"
- );
- var scratchHPRQuaternion$1 = new Quaternion();
- var scratchScale$2 = new Cartesian2.Cartesian3(1.0, 1.0, 1.0);
- var scratchHPRMatrix4 = new Matrix4();
- /**
- * Computes a 4x4 transformation matrix from a reference frame with axes computed from the heading-pitch-roll angles
- * centered at the provided origin to the provided ellipsoid's fixed reference frame. Heading is the rotation from the local north
- * direction where a positive angle is increasing eastward. Pitch is the rotation from the local east-north plane. Positive pitch angles
- * are above the plane. Negative pitch angles are below the plane. Roll is the first rotation applied about the local east axis.
- *
- * @param {Cartesian3} origin The center point of the local reference frame.
- * @param {HeadingPitchRoll} headingPitchRoll The heading, pitch, and roll.
- * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid whose fixed frame is used in the transformation.
- * @param {Transforms.LocalFrameToFixedFrame} [fixedFrameTransform=Transforms.eastNorthUpToFixedFrame] A 4x4 transformation
- * matrix from a reference frame to the provided ellipsoid's fixed reference frame
- * @param {Matrix4} [result] The object onto which to store the result.
- * @returns {Matrix4} The modified result parameter or a new Matrix4 instance if none was provided.
- *
- * @example
- * // Get the transform from local heading-pitch-roll at cartographic (0.0, 0.0) to Earth's fixed frame.
- * var center = Cesium.Cartesian3.fromDegrees(0.0, 0.0);
- * var heading = -Cesium.Math.PI_OVER_TWO;
- * var pitch = Cesium.Math.PI_OVER_FOUR;
- * var roll = 0.0;
- * var hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);
- * var transform = Cesium.Transforms.headingPitchRollToFixedFrame(center, hpr);
- */
- Transforms.headingPitchRollToFixedFrame = function (
- origin,
- headingPitchRoll,
- ellipsoid,
- fixedFrameTransform,
- result
- ) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("HeadingPitchRoll", headingPitchRoll);
- //>>includeEnd('debug');
- fixedFrameTransform = when.defaultValue(
- fixedFrameTransform,
- Transforms.eastNorthUpToFixedFrame
- );
- var hprQuaternion = Quaternion.fromHeadingPitchRoll(
- headingPitchRoll,
- scratchHPRQuaternion$1
- );
- var hprMatrix = Matrix4.fromTranslationQuaternionRotationScale(
- Cartesian2.Cartesian3.ZERO,
- hprQuaternion,
- scratchScale$2,
- scratchHPRMatrix4
- );
- result = fixedFrameTransform(origin, ellipsoid, result);
- return Matrix4.multiply(result, hprMatrix, result);
- };
- var scratchENUMatrix4 = new Matrix4();
- var scratchHPRMatrix3 = new Matrix3();
- /**
- * Computes a quaternion from a reference frame with axes computed from the heading-pitch-roll angles
- * centered at the provided origin. Heading is the rotation from the local north
- * direction where a positive angle is increasing eastward. Pitch is the rotation from the local east-north plane. Positive pitch angles
- * are above the plane. Negative pitch angles are below the plane. Roll is the first rotation applied about the local east axis.
- *
- * @param {Cartesian3} origin The center point of the local reference frame.
- * @param {HeadingPitchRoll} headingPitchRoll The heading, pitch, and roll.
- * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid whose fixed frame is used in the transformation.
- * @param {Transforms.LocalFrameToFixedFrame} [fixedFrameTransform=Transforms.eastNorthUpToFixedFrame] A 4x4 transformation
- * matrix from a reference frame to the provided ellipsoid's fixed reference frame
- * @param {Quaternion} [result] The object onto which to store the result.
- * @returns {Quaternion} The modified result parameter or a new Quaternion instance if none was provided.
- *
- * @example
- * // Get the quaternion from local heading-pitch-roll at cartographic (0.0, 0.0) to Earth's fixed frame.
- * var center = Cesium.Cartesian3.fromDegrees(0.0, 0.0);
- * var heading = -Cesium.Math.PI_OVER_TWO;
- * var pitch = Cesium.Math.PI_OVER_FOUR;
- * var roll = 0.0;
- * var hpr = new HeadingPitchRoll(heading, pitch, roll);
- * var quaternion = Cesium.Transforms.headingPitchRollQuaternion(center, hpr);
- */
- Transforms.headingPitchRollQuaternion = function (
- origin,
- headingPitchRoll,
- ellipsoid,
- fixedFrameTransform,
- result
- ) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.typeOf.object("HeadingPitchRoll", headingPitchRoll);
- //>>includeEnd('debug');
- var transform = Transforms.headingPitchRollToFixedFrame(
- origin,
- headingPitchRoll,
- ellipsoid,
- fixedFrameTransform,
- scratchENUMatrix4
- );
- var rotation = Matrix4.getMatrix3(transform, scratchHPRMatrix3);
- return Quaternion.fromRotationMatrix(rotation, result);
- };
- var noScale = new Cartesian2.Cartesian3(1.0, 1.0, 1.0);
- var hprCenterScratch = new Cartesian2.Cartesian3();
- var ffScratch = new Matrix4();
- var hprTransformScratch = new Matrix4();
- var hprRotationScratch = new Matrix3();
- var hprQuaternionScratch = new Quaternion();
- /**
- * Computes heading-pitch-roll angles from a transform in a particular reference frame. Heading is the rotation from the local north
- * direction where a positive angle is increasing eastward. Pitch is the rotation from the local east-north plane. Positive pitch angles
- * are above the plane. Negative pitch angles are below the plane. Roll is the first rotation applied about the local east axis.
- *
- * @param {Matrix4} transform The transform
- * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid whose fixed frame is used in the transformation.
- * @param {Transforms.LocalFrameToFixedFrame} [fixedFrameTransform=Transforms.eastNorthUpToFixedFrame] A 4x4 transformation
- * matrix from a reference frame to the provided ellipsoid's fixed reference frame
- * @param {HeadingPitchRoll} [result] The object onto which to store the result.
- * @returns {HeadingPitchRoll} The modified result parameter or a new HeadingPitchRoll instance if none was provided.
- */
- Transforms.fixedFrameToHeadingPitchRoll = function (
- transform,
- ellipsoid,
- fixedFrameTransform,
- result
- ) {
- //>>includeStart('debug', pragmas.debug);
- Check.Check.defined("transform", transform);
- //>>includeEnd('debug');
- ellipsoid = when.defaultValue(ellipsoid, Cartesian2.Ellipsoid.WGS84);
- fixedFrameTransform = when.defaultValue(
- fixedFrameTransform,
- Transforms.eastNorthUpToFixedFrame
- );
- if (!when.defined(result)) {
- result = new HeadingPitchRoll();
- }
- var center = Matrix4.getTranslation(transform, hprCenterScratch);
- if (Cartesian2.Cartesian3.equals(center, Cartesian2.Cartesian3.ZERO)) {
- result.heading = 0;
- result.pitch = 0;
- result.roll = 0;
- return result;
- }
- var toFixedFrame = Matrix4.inverseTransformation(
- fixedFrameTransform(center, ellipsoid, ffScratch),
- ffScratch
- );
- var transformCopy = Matrix4.setScale(transform, noScale, hprTransformScratch);
- transformCopy = Matrix4.setTranslation(
- transformCopy,
- Cartesian2.Cartesian3.ZERO,
- transformCopy
- );
- toFixedFrame = Matrix4.multiply(toFixedFrame, transformCopy, toFixedFrame);
- var quaternionRotation = Quaternion.fromRotationMatrix(
- Matrix4.getMatrix3(toFixedFrame, hprRotationScratch),
- hprQuaternionScratch
- );
- quaternionRotation = Quaternion.normalize(
- quaternionRotation,
- quaternionRotation
- );
- return HeadingPitchRoll.fromQuaternion(quaternionRotation, result);
- };
- var gmstConstant0 = 6 * 3600 + 41 * 60 + 50.54841;
- var gmstConstant1 = 8640184.812866;
- var gmstConstant2 = 0.093104;
- var gmstConstant3 = -6.2e-6;
- var rateCoef = 1.1772758384668e-19;
- var wgs84WRPrecessing = 7.2921158553e-5;
- var twoPiOverSecondsInDay = _Math.CesiumMath.TWO_PI / 86400.0;
- var dateInUtc = new JulianDate();
- /**
- * Computes a rotation matrix to transform a point or vector from True Equator Mean Equinox (TEME) axes to the
- * pseudo-fixed axes at a given time. This method treats the UT1 time standard as equivalent to UTC.
- *
- * @param {JulianDate} date The time at which to compute the rotation matrix.
- * @param {Matrix3} [result] The object onto which to store the result.
- * @returns {Matrix3} The modified result parameter or a new Matrix3 instance if none was provided.
- *
- * @example
- * //Set the view to the inertial frame.
- * scene.postUpdate.addEventListener(function(scene, time) {
- * var now = Cesium.JulianDate.now();
- * var offset = Cesium.Matrix4.multiplyByPoint(camera.transform, camera.position, new Cesium.Cartesian3());
- * var transform = Cesium.Matrix4.fromRotationTranslation(Cesium.Transforms.computeTemeToPseudoFixedMatrix(now));
- * var inverseTransform = Cesium.Matrix4.inverseTransformation(transform, new Cesium.Matrix4());
- * Cesium.Matrix4.multiplyByPoint(inverseTransform, offset, offset);
- * camera.lookAtTransform(transform, offset);
- * });
- */
- Transforms.computeTemeToPseudoFixedMatrix = function (date, result) {
- //>>includeStart('debug', pragmas.debug);
- if (!when.defined(date)) {
- throw new Check.DeveloperError("date is required.");
- }
- //>>includeEnd('debug');
- // GMST is actually computed using UT1. We're using UTC as an approximation of UT1.
- // We do not want to use the function like convertTaiToUtc in JulianDate because
- // we explicitly do not want to fail when inside the leap second.
- dateInUtc = JulianDate.addSeconds(
- date,
- -JulianDate.computeTaiMinusUtc(date),
- dateInUtc
- );
- var utcDayNumber = dateInUtc.dayNumber;
- var utcSecondsIntoDay = dateInUtc.secondsOfDay;
- var t;
- var diffDays = utcDayNumber - 2451545;
- if (utcSecondsIntoDay >= 43200.0) {
- t = (diffDays + 0.5) / TimeConstants$1.DAYS_PER_JULIAN_CENTURY;
- } else {
- t = (diffDays - 0.5) / TimeConstants$1.DAYS_PER_JULIAN_CENTURY;
- }
- var gmst0 =
- gmstConstant0 +
- t * (gmstConstant1 + t * (gmstConstant2 + t * gmstConstant3));
- var angle = (gmst0 * twoPiOverSecondsInDay) % _Math.CesiumMath.TWO_PI;
- var ratio = wgs84WRPrecessing + rateCoef * (utcDayNumber - 2451545.5);
- var secondsSinceMidnight =
- (utcSecondsIntoDay + TimeConstants$1.SECONDS_PER_DAY * 0.5) %
- TimeConstants$1.SECONDS_PER_DAY;
- var gha = angle + ratio * secondsSinceMidnight;
- var cosGha = Math.cos(gha);
- var sinGha = Math.sin(gha);
- if (!when.defined(result)) {
- return new Matrix3(
- cosGha,
- sinGha,
- 0.0,
- -sinGha,
- cosGha,
- 0.0,
- 0.0,
- 0.0,
- 1.0
- );
- }
- result[0] = cosGha;
- result[1] = -sinGha;
- result[2] = 0.0;
- result[3] = sinGha;
- result[4] = cosGha;
- result[5] = 0.0;
- result[6] = 0.0;
- result[7] = 0.0;
- result[8] = 1.0;
- return result;
- };
- /**
- * The source of IAU 2006 XYS data, used for computing the transformation between the
- * Fixed and ICRF axes.
- * @type {Iau2006XysData}
- *
- * @see Transforms.computeIcrfToFixedMatrix
- * @see Transforms.computeFixedToIcrfMatrix
- *
- * @private
- */
- Transforms.iau2006XysData = new Iau2006XysData();
- /**
- * The source of Earth Orientation Parameters (EOP) data, used for computing the transformation
- * between the Fixed and ICRF axes. By default, zero values are used for all EOP values,
- * yielding a reasonable but not completely accurate representation of the ICRF axes.
- * @type {EarthOrientationParameters}
- *
- * @see Transforms.computeIcrfToFixedMatrix
- * @see Transforms.computeFixedToIcrfMatrix
- *
- * @private
- */
- Transforms.earthOrientationParameters = EarthOrientationParameters.NONE;
- var ttMinusTai = 32.184;
- var j2000ttDays = 2451545.0;
- /**
- * Preloads the data necessary to transform between the ICRF and Fixed axes, in either
- * direction, over a given interval. This function returns a promise that, when resolved,
- * indicates that the preload has completed.
- *
- * @param {TimeInterval} timeInterval The interval to preload.
- * @returns {Promise<void>} A promise that, when resolved, indicates that the preload has completed
- * and evaluation of the transformation between the fixed and ICRF axes will
- * no longer return undefined for a time inside the interval.
- *
- *
- * @example
- * var interval = new Cesium.TimeInterval(...);
- * when(Cesium.Transforms.preloadIcrfFixed(interval), function() {
- * // the data is now loaded
- * });
- *
- * @see Transforms.computeIcrfToFixedMatrix
- * @see Transforms.computeFixedToIcrfMatrix
- * @see when
- */
- Transforms.preloadIcrfFixed = function (timeInterval) {
- var startDayTT = timeInterval.start.dayNumber;
- var startSecondTT = timeInterval.start.secondsOfDay + ttMinusTai;
- var stopDayTT = timeInterval.stop.dayNumber;
- var stopSecondTT = timeInterval.stop.secondsOfDay + ttMinusTai;
- var xysPromise = Transforms.iau2006XysData.preload(
- startDayTT,
- startSecondTT,
- stopDayTT,
- stopSecondTT
- );
- var eopPromise = Transforms.earthOrientationParameters.getPromiseToLoad();
- return when.when.all([xysPromise, eopPromise]);
- };
- /**
- * Computes a rotation matrix to transform a point or vector from the International Celestial
- * Reference Frame (GCRF/ICRF) inertial frame axes to the Earth-Fixed frame axes (ITRF)
- * at a given time. This function may return undefined if the data necessary to
- * do the transformation is not yet loaded.
- *
- * @param {JulianDate} date The time at which to compute the rotation matrix.
- * @param {Matrix3} [result] The object onto which to store the result. If this parameter is
- * not specified, a new instance is created and returned.
- * @returns {Matrix3} The rotation matrix, or undefined if the data necessary to do the
- * transformation is not yet loaded.
- *
- *
- * @example
- * scene.postUpdate.addEventListener(function(scene, time) {
- * // View in ICRF.
- * var icrfToFixed = Cesium.Transforms.computeIcrfToFixedMatrix(time);
- * if (Cesium.defined(icrfToFixed)) {
- * var offset = Cesium.Cartesian3.clone(camera.position);
- * var transform = Cesium.Matrix4.fromRotationTranslation(icrfToFixed);
- * camera.lookAtTransform(transform, offset);
- * }
- * });
- *
- * @see Transforms.preloadIcrfFixed
- */
- Transforms.computeIcrfToFixedMatrix = function (date, result) {
- //>>includeStart('debug', pragmas.debug);
- if (!when.defined(date)) {
- throw new Check.DeveloperError("date is required.");
- }
- //>>includeEnd('debug');
- if (!when.defined(result)) {
- result = new Matrix3();
- }
- var fixedToIcrfMtx = Transforms.computeFixedToIcrfMatrix(date, result);
- if (!when.defined(fixedToIcrfMtx)) {
- return undefined;
- }
- return Matrix3.transpose(fixedToIcrfMtx, result);
- };
- var xysScratch = new Iau2006XysSample(0.0, 0.0, 0.0);
- var eopScratch = new EarthOrientationParametersSample(
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- 0.0
- );
- var rotation1Scratch = new Matrix3();
- var rotation2Scratch = new Matrix3();
- /**
- * Computes a rotation matrix to transform a point or vector from the Earth-Fixed frame axes (ITRF)
- * to the International Celestial Reference Frame (GCRF/ICRF) inertial frame axes
- * at a given time. This function may return undefined if the data necessary to
- * do the transformation is not yet loaded.
- *
- * @param {JulianDate} date The time at which to compute the rotation matrix.
- * @param {Matrix3} [result] The object onto which to store the result. If this parameter is
- * not specified, a new instance is created and returned.
- * @returns {Matrix3} The rotation matrix, or undefined if the data necessary to do the
- * transformation is not yet loaded.
- *
- *
- * @example
- * // Transform a point from the ICRF axes to the Fixed axes.
- * var now = Cesium.JulianDate.now();
- * var pointInFixed = Cesium.Cartesian3.fromDegrees(0.0, 0.0);
- * var fixedToIcrf = Cesium.Transforms.computeIcrfToFixedMatrix(now);
- * var pointInInertial = new Cesium.Cartesian3();
- * if (Cesium.defined(fixedToIcrf)) {
- * pointInInertial = Cesium.Matrix3.multiplyByVector(fixedToIcrf, pointInFixed, pointInInertial);
- * }
- *
- * @see Transforms.preloadIcrfFixed
- */
- Transforms.computeFixedToIcrfMatrix = function (date, result) {
- //>>includeStart('debug', pragmas.debug);
- if (!when.defined(date)) {
- throw new Check.DeveloperError("date is required.");
- }
- //>>includeEnd('debug');
- if (!when.defined(result)) {
- result = new Matrix3();
- }
- // Compute pole wander
- var eop = Transforms.earthOrientationParameters.compute(date, eopScratch);
- if (!when.defined(eop)) {
- return undefined;
- }
- // There is no external conversion to Terrestrial Time (TT).
- // So use International Atomic Time (TAI) and convert using offsets.
- // Here we are assuming that dayTT and secondTT are positive
- var dayTT = date.dayNumber;
- // It's possible here that secondTT could roll over 86400
- // This does not seem to affect the precision (unit tests check for this)
- var secondTT = date.secondsOfDay + ttMinusTai;
- var xys = Transforms.iau2006XysData.computeXysRadians(
- dayTT,
- secondTT,
- xysScratch
- );
- if (!when.defined(xys)) {
- return undefined;
- }
- var x = xys.x + eop.xPoleOffset;
- var y = xys.y + eop.yPoleOffset;
- // Compute XYS rotation
- var a = 1.0 / (1.0 + Math.sqrt(1.0 - x * x - y * y));
- var rotation1 = rotation1Scratch;
- rotation1[0] = 1.0 - a * x * x;
- rotation1[3] = -a * x * y;
- rotation1[6] = x;
- rotation1[1] = -a * x * y;
- rotation1[4] = 1 - a * y * y;
- rotation1[7] = y;
- rotation1[2] = -x;
- rotation1[5] = -y;
- rotation1[8] = 1 - a * (x * x + y * y);
- var rotation2 = Matrix3.fromRotationZ(-xys.s, rotation2Scratch);
- var matrixQ = Matrix3.multiply(rotation1, rotation2, rotation1Scratch);
- // Similar to TT conversions above
- // It's possible here that secondTT could roll over 86400
- // This does not seem to affect the precision (unit tests check for this)
- var dateUt1day = date.dayNumber;
- var dateUt1sec =
- date.secondsOfDay - JulianDate.computeTaiMinusUtc(date) + eop.ut1MinusUtc;
- // Compute Earth rotation angle
- // The IERS standard for era is
- // era = 0.7790572732640 + 1.00273781191135448 * Tu
- // where
- // Tu = JulianDateInUt1 - 2451545.0
- // However, you get much more precision if you make the following simplification
- // era = a + (1 + b) * (JulianDayNumber + FractionOfDay - 2451545)
- // era = a + (JulianDayNumber - 2451545) + FractionOfDay + b (JulianDayNumber - 2451545 + FractionOfDay)
- // era = a + FractionOfDay + b (JulianDayNumber - 2451545 + FractionOfDay)
- // since (JulianDayNumber - 2451545) represents an integer number of revolutions which will be discarded anyway.
- var daysSinceJ2000 = dateUt1day - 2451545;
- var fractionOfDay = dateUt1sec / TimeConstants$1.SECONDS_PER_DAY;
- var era =
- 0.779057273264 +
- fractionOfDay +
- 0.00273781191135448 * (daysSinceJ2000 + fractionOfDay);
- era = (era % 1.0) * _Math.CesiumMath.TWO_PI;
- var earthRotation = Matrix3.fromRotationZ(era, rotation2Scratch);
- // pseudoFixed to ICRF
- var pfToIcrf = Matrix3.multiply(matrixQ, earthRotation, rotation1Scratch);
- // Compute pole wander matrix
- var cosxp = Math.cos(eop.xPoleWander);
- var cosyp = Math.cos(eop.yPoleWander);
- var sinxp = Math.sin(eop.xPoleWander);
- var sinyp = Math.sin(eop.yPoleWander);
- var ttt = dayTT - j2000ttDays + secondTT / TimeConstants$1.SECONDS_PER_DAY;
- ttt /= 36525.0;
- // approximate sp value in rad
- var sp = (-47.0e-6 * ttt * _Math.CesiumMath.RADIANS_PER_DEGREE) / 3600.0;
- var cossp = Math.cos(sp);
- var sinsp = Math.sin(sp);
- var fToPfMtx = rotation2Scratch;
- fToPfMtx[0] = cosxp * cossp;
- fToPfMtx[1] = cosxp * sinsp;
- fToPfMtx[2] = sinxp;
- fToPfMtx[3] = -cosyp * sinsp + sinyp * sinxp * cossp;
- fToPfMtx[4] = cosyp * cossp + sinyp * sinxp * sinsp;
- fToPfMtx[5] = -sinyp * cosxp;
- fToPfMtx[6] = -sinyp * sinsp - cosyp * sinxp * cossp;
- fToPfMtx[7] = sinyp * cossp - cosyp * sinxp * sinsp;
- fToPfMtx[8] = cosyp * cosxp;
- return Matrix3.multiply(pfToIcrf, fToPfMtx, result);
- };
- var pointToWindowCoordinatesTemp = new Cartesian4();
- /**
- * Transform a point from model coordinates to window coordinates.
- *
- * @param {Matrix4} modelViewProjectionMatrix The 4x4 model-view-projection matrix.
- * @param {Matrix4} viewportTransformation The 4x4 viewport transformation.
- * @param {Cartesian3} point The point to transform.
- * @param {Cartesian2} [result] The object onto which to store the result.
- * @returns {Cartesian2} The modified result parameter or a new Cartesian2 instance if none was provided.
- */
- Transforms.pointToWindowCoordinates = function (
- modelViewProjectionMatrix,
- viewportTransformation,
- point,
- result
- ) {
- result = Transforms.pointToGLWindowCoordinates(
- modelViewProjectionMatrix,
- viewportTransformation,
- point,
- result
- );
- result.y = 2.0 * viewportTransformation[5] - result.y;
- return result;
- };
- /**
- * @private
- */
- Transforms.pointToGLWindowCoordinates = function (
- modelViewProjectionMatrix,
- viewportTransformation,
- point,
- result
- ) {
- //>>includeStart('debug', pragmas.debug);
- if (!when.defined(modelViewProjectionMatrix)) {
- throw new Check.DeveloperError("modelViewProjectionMatrix is required.");
- }
- if (!when.defined(viewportTransformation)) {
- throw new Check.DeveloperError("viewportTransformation is required.");
- }
- if (!when.defined(point)) {
- throw new Check.DeveloperError("point is required.");
- }
- //>>includeEnd('debug');
- if (!when.defined(result)) {
- result = new Cartesian2.Cartesian2();
- }
- var tmp = pointToWindowCoordinatesTemp;
- Matrix4.multiplyByVector(
- modelViewProjectionMatrix,
- Cartesian4.fromElements(point.x, point.y, point.z, 1, tmp),
- tmp
- );
- Cartesian4.multiplyByScalar(tmp, 1.0 / tmp.w, tmp);
- Matrix4.multiplyByVector(viewportTransformation, tmp, tmp);
- return Cartesian2.Cartesian2.fromCartesian4(tmp, result);
- };
- var normalScratch = new Cartesian2.Cartesian3();
- var rightScratch = new Cartesian2.Cartesian3();
- var upScratch = new Cartesian2.Cartesian3();
- /**
- * Transform a position and velocity to a rotation matrix.
- *
- * @param {Cartesian3} position The position to transform.
- * @param {Cartesian3} velocity The velocity vector to transform.
- * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid whose fixed frame is used in the transformation.
- * @param {Matrix3} [result] The object onto which to store the result.
- * @returns {Matrix3} The modified result parameter or a new Matrix3 instance if none was provided.
- */
- Transforms.rotationMatrixFromPositionVelocity = function (
- position,
- velocity,
- ellipsoid,
- result
- ) {
- //>>includeStart('debug', pragmas.debug);
- if (!when.defined(position)) {
- throw new Check.DeveloperError("position is required.");
- }
- if (!when.defined(velocity)) {
- throw new Check.DeveloperError("velocity is required.");
- }
- //>>includeEnd('debug');
- var normal = when.defaultValue(ellipsoid, Cartesian2.Ellipsoid.WGS84).geodeticSurfaceNormal(
- position,
- normalScratch
- );
- var right = Cartesian2.Cartesian3.cross(velocity, normal, rightScratch);
- if (Cartesian2.Cartesian3.equalsEpsilon(right, Cartesian2.Cartesian3.ZERO, _Math.CesiumMath.EPSILON6)) {
- right = Cartesian2.Cartesian3.clone(Cartesian2.Cartesian3.UNIT_X, right);
- }
- var up = Cartesian2.Cartesian3.cross(right, velocity, upScratch);
- Cartesian2.Cartesian3.normalize(up, up);
- Cartesian2.Cartesian3.cross(velocity, up, right);
- Cartesian2.Cartesian3.negate(right, right);
- Cartesian2.Cartesian3.normalize(right, right);
- if (!when.defined(result)) {
- result = new Matrix3();
- }
- result[0] = velocity.x;
- result[1] = velocity.y;
- result[2] = velocity.z;
- result[3] = right.x;
- result[4] = right.y;
- result[5] = right.z;
- result[6] = up.x;
- result[7] = up.y;
- result[8] = up.z;
- return result;
- };
- var swizzleMatrix = new Matrix4(
- 0.0,
- 0.0,
- 1.0,
- 0.0,
- 1.0,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- 1.0,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- 0.0,
- 1.0
- );
- var scratchCartographic = new Cartesian2.Cartographic();
- var scratchCartesian3Projection = new Cartesian2.Cartesian3();
- var scratchCenter = new Cartesian2.Cartesian3();
- var scratchRotation = new Matrix3();
- var scratchFromENU = new Matrix4();
- var scratchToENU = new Matrix4();
- /**
- * @private
- */
- Transforms.basisTo2D = function (projection, matrix, result) {
- //>>includeStart('debug', pragmas.debug);
- if (!when.defined(projection)) {
- throw new Check.DeveloperError("projection is required.");
- }
- if (!when.defined(matrix)) {
- throw new Check.DeveloperError("matrix is required.");
- }
- if (!when.defined(result)) {
- throw new Check.DeveloperError("result is required.");
- }
- //>>includeEnd('debug');
- var rtcCenter = Matrix4.getTranslation(matrix, scratchCenter);
- var ellipsoid = projection.ellipsoid;
- // Get the 2D Center
- var cartographic = ellipsoid.cartesianToCartographic(
- rtcCenter,
- scratchCartographic
- );
- var projectedPosition = projection.project(
- cartographic,
- scratchCartesian3Projection
- );
- Cartesian2.Cartesian3.fromElements(
- projectedPosition.z,
- projectedPosition.x,
- projectedPosition.y,
- projectedPosition
- );
- // Assuming the instance are positioned in WGS84, invert the WGS84 transform to get the local transform and then convert to 2D
- var fromENU = Transforms.eastNorthUpToFixedFrame(
- rtcCenter,
- ellipsoid,
- scratchFromENU
- );
- var toENU = Matrix4.inverseTransformation(fromENU, scratchToENU);
- var rotation = Matrix4.getMatrix3(matrix, scratchRotation);
- var local = Matrix4.multiplyByMatrix3(toENU, rotation, result);
- Matrix4.multiply(swizzleMatrix, local, result); // Swap x, y, z for 2D
- Matrix4.setTranslation(result, projectedPosition, result); // Use the projected center
- return result;
- };
- /**
- * @private
- */
- Transforms.wgs84To2DModelMatrix = function (projection, center, result) {
- //>>includeStart('debug', pragmas.debug);
- if (!when.defined(projection)) {
- throw new Check.DeveloperError("projection is required.");
- }
- if (!when.defined(center)) {
- throw new Check.DeveloperError("center is required.");
- }
- if (!when.defined(result)) {
- throw new Check.DeveloperError("result is required.");
- }
- //>>includeEnd('debug');
- var ellipsoid = projection.ellipsoid;
- var fromENU = Transforms.eastNorthUpToFixedFrame(
- center,
- ellipsoid,
- scratchFromENU
- );
- var toENU = Matrix4.inverseTransformation(fromENU, scratchToENU);
- var cartographic = ellipsoid.cartesianToCartographic(
- center,
- scratchCartographic
- );
- var projectedPosition = projection.project(
- cartographic,
- scratchCartesian3Projection
- );
- Cartesian2.Cartesian3.fromElements(
- projectedPosition.z,
- projectedPosition.x,
- projectedPosition.y,
- projectedPosition
- );
- var translation = Matrix4.fromTranslation(projectedPosition, scratchFromENU);
- Matrix4.multiply(swizzleMatrix, toENU, result);
- Matrix4.multiply(translation, result, result);
- return result;
- };
- exports.BoundingSphere = BoundingSphere;
- exports.Cartesian4 = Cartesian4;
- exports.FeatureDetection = FeatureDetection;
- exports.GeographicProjection = GeographicProjection;
- exports.Intersect = Intersect$1;
- exports.Interval = Interval;
- exports.Matrix3 = Matrix3;
- exports.Matrix4 = Matrix4;
- exports.Quaternion = Quaternion;
- exports.Resource = Resource;
- exports.Transforms = Transforms;
- exports.buildModuleUrl = buildModuleUrl;
- });
|