diff --git a/DataAndTools/YouTubePopUp.css b/DataAndTools/YouTubePopUp.css new file mode 100755 index 0000000..fa90e67 --- /dev/null +++ b/DataAndTools/YouTubePopUp.css @@ -0,0 +1,153 @@ +@charset "UTF-8"; + +/* + Name: YouTubePopUp + Description: jQuery plugin to display YouTube video in PopUp, responsive and retina, easy to use. + Version: 1.0.0 + Plugin URL: http://wp-time.com/youtube-popup-jquery-plugin/ + Written By: Qassim Hassan + Twitter: @QQQHZ + Websites: wp-time.com | qass.im | wp-plugins.in + Dual licensed under the MIT and GPL licenses: + http://www.opensource.org/licenses/mit-license.php + http://www.gnu.org/licenses/gpl.html + Copyright (c) 2016 - Qassim Hassan +*/ + +.YouTubePopUp-Wrap{ + position:fixed; + width:100%; + height:100%; + background-color:#000; + background-color:rgba(0,0,0,0.8); + top:0; + left:0; + opacity: 0; + z-index:9999999999999; + -webkit-animation-duration: 0.5s; + animation-duration: 0.5s; + -webkit-animation-fill-mode: both; + animation-fill-mode: both; + -webkit-animation-name: YouTubePopUp; + animation-name: YouTubePopUp; +} + +@-webkit-keyframes YouTubePopUp { + 0% { + opacity: 0; + } + + 100% { + opacity: 1; + } +} + +@keyframes YouTubePopUp { + 0% { + opacity: 0; + } + + 100% { + opacity: 1; + } +} + +body.logged-in .YouTubePopUp-Wrap{ /* For WordPress */ + top:32px; + z-index:99998; +} + +.YouTubePopUp-Content{ + max-width:800px; + display:block; + margin:0 auto; + height:100%; + position:relative; +} + +.YouTubePopUp-Content iframe{ + max-width:100% !important; + width:100% !important; + display:block !important; + height:480px !important; + border:none !important; + position:absolute; + top: 0; + bottom: 0; + margin: auto 0; +} + +.YouTubePopUp-Hide{ + -webkit-animation-duration: 0.5s; + animation-duration: 0.5s; + -webkit-animation-fill-mode: both; + animation-fill-mode: both; + -webkit-animation-name: YouTubePopUpHide; + animation-name: YouTubePopUpHide; +} + +@-webkit-keyframes YouTubePopUpHide { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + } +} + +@keyframes YouTubePopUpHide { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + } +} + +.YouTubePopUp-Close{ + position:absolute; + top:0; + cursor:pointer; + bottom:528px; + right:0px; + margin:auto 0; + width:24px; + height:24px; + background:url(close.png) no-repeat; + background-size:24px 24px; + -webkit-background-size:24px 24px; + -moz-background-size:24px 24px; + -o-background-size:24px 24px; +} + +.YouTubePopUp-Close:hover{ + opacity:0.5; +} + +@media all and (max-width: 768px) and (min-width: 10px){ + .YouTubePopUp-Content{ + max-width:90%; + } +} + +@media all and (max-width: 600px) and (min-width: 10px){ + .YouTubePopUp-Content iframe{ + height:320px !important; + } + + .YouTubePopUp-Close{ + bottom:362px; + } +} + +@media all and (max-width: 480px) and (min-width: 10px){ + .YouTubePopUp-Content iframe{ + height:220px !important; + } + + .YouTubePopUp-Close{ + bottom:262px; + } +} diff --git a/DataAndTools/YouTubePopUp.jquery.js b/DataAndTools/YouTubePopUp.jquery.js new file mode 100755 index 0000000..5ea0849 --- /dev/null +++ b/DataAndTools/YouTubePopUp.jquery.js @@ -0,0 +1,75 @@ +/* + Name: YouTubePopUp + Description: jQuery plugin to display YouTube or Vimeo video in PopUp, responsive and retina, easy to use. + Version: 1.0.0 + Plugin URL: http://wp-time.com/youtube-popup-jquery-plugin/ + Written By: Qassim Hassan + Twitter: @QQQHZ + Websites: wp-time.com | qass.im | wp-plugins.in + Dual licensed under the MIT and GPL licenses: + http://www.opensource.org/licenses/mit-license.php + http://www.gnu.org/licenses/gpl.html + Copyright (c) 2016 - Qassim Hassan +*/ + +(function ( $ ) { + + $.fn.YouTubePopUp = function(options) { + + var YouTubePopUpOptions = $.extend({ + autoplay: 1 + }, options ); + + $(this).on('click', function (e) { + + var youtubeLink = $(this).attr("href"); + + if( youtubeLink.match(/(youtube.com)/) ){ + var split_c = "v="; + var split_n = 1; + } + + if( youtubeLink.match(/(youtu.be)/) || youtubeLink.match(/(vimeo.com\/)+[0-9]/) ){ + var split_c = "/"; + var split_n = 3; + } + + if( youtubeLink.match(/(vimeo.com\/)+[a-zA-Z]/) ){ + var split_c = "/"; + var split_n = 5; + } + + var getYouTubeVideoID = youtubeLink.split(split_c)[split_n]; + + var cleanVideoID = getYouTubeVideoID.replace(/(&)+(.*)/, ""); + + if( youtubeLink.match(/(youtu.be)/) || youtubeLink.match(/(youtube.com)/) ){ + var videoEmbedLink = "https://www.youtube.com/embed/"+cleanVideoID+"?autoplay="+YouTubePopUpOptions.autoplay+""; + } + + if( youtubeLink.match(/(vimeo.com\/)+[0-9]/) || youtubeLink.match(/(vimeo.com\/)+[a-zA-Z]/) ){ + var videoEmbedLink = "https://player.vimeo.com/video/"+cleanVideoID+"?autoplay="+YouTubePopUpOptions.autoplay+""; + } + + $("body").append('
'); + + + $(".YouTubePopUp-Wrap, .YouTubePopUp-Close").click(function(){ + $(".YouTubePopUp-Wrap").addClass("YouTubePopUp-Hide").delay(515).queue(function() { $(this).remove(); }); + }); + + e.preventDefault(); + + }); + + $(document).keyup(function(e) { + + if ( e.keyCode == 27 ){ + $('.YouTubePopUp-Wrap, .YouTubePopUp-Close').click(); + } + + }); + + }; + +}( jQuery )); \ No newline at end of file diff --git a/DataAndTools/close.png b/DataAndTools/close.png new file mode 100755 index 0000000..6dd0991 Binary files /dev/null and b/DataAndTools/close.png differ diff --git a/DataAndTools/pictures/github_view.png b/DataAndTools/pictures/github_view.png index 0b7b24d..530c864 100644 Binary files a/DataAndTools/pictures/github_view.png and b/DataAndTools/pictures/github_view.png differ diff --git a/DataAndTools/pictures/handmade_ROOTbrowser.png b/DataAndTools/pictures/handmade_ROOTbrowser.png new file mode 100644 index 0000000..a4cc241 Binary files /dev/null and b/DataAndTools/pictures/handmade_ROOTbrowser.png differ diff --git a/DataAndTools/pictures/handmade_WebAnalyser.png b/DataAndTools/pictures/handmade_WebAnalyser.png new file mode 100644 index 0000000..3ea162d Binary files /dev/null and b/DataAndTools/pictures/handmade_WebAnalyser.png differ diff --git a/DataAndTools/pictures/handmade_software.png b/DataAndTools/pictures/handmade_software.png new file mode 100644 index 0000000..f542745 Binary files /dev/null and b/DataAndTools/pictures/handmade_software.png differ diff --git a/DataAndTools/pictures/old_github_view.png b/DataAndTools/pictures/old_github_view.png new file mode 100644 index 0000000..0b7b24d Binary files /dev/null and b/DataAndTools/pictures/old_github_view.png differ diff --git a/DataAndTools/pictures/youtube_icon.png b/DataAndTools/pictures/youtube_icon.png new file mode 100644 index 0000000..169821a Binary files /dev/null and b/DataAndTools/pictures/youtube_icon.png differ diff --git a/DataAndTools/repository.php b/DataAndTools/repository.php index d20b175..9102d82 100644 --- a/DataAndTools/repository.php +++ b/DataAndTools/repository.php @@ -51,7 +51,7 @@
- +
diff --git a/community.php b/community.php index ca726bc..0ac562d 100644 --- a/community.php +++ b/community.php @@ -26,9 +26,13 @@

+
- Community + Community +
+ +
diff --git a/community/contact.php b/community/contact.php index 3005f44..2940447 100644 --- a/community/contact.php +++ b/community/contact.php @@ -44,6 +44,7 @@

Contact

+

atlas.outreach.data.tools@cern.ch

diff --git a/extendedanalysis/datasets.php b/extendedanalysis/datasets.php index c06b304..858e190 100644 --- a/extendedanalysis/datasets.php +++ b/extendedanalysis/datasets.php @@ -19,7 +19,7 @@

- Data & Tools - VMs + Data & Tools - datasets diff --git a/extendedanalysis/dev_datasets.php b/extendedanalysis/dev_datasets.php new file mode 100644 index 0000000..8ea72fe --- /dev/null +++ b/extendedanalysis/dev_datasets.php @@ -0,0 +1,492 @@ + + +
+ +
+ + +
+
+

Level 3: Data & Tools - Datasets

+
+ + +
+ + + + + +
+ + + + + + + +
+ + + +

+ Download the ATLAS open datasets complete collection in a .ZIP file or a subset as single ROOT files. + Don't forget to grab the software or the Virtual Machines to carry out your analysis. +

+
+ Data & Tools - datasets +
+
+ + + + +
+
+ + +
+
+

Set of MonteCarlo (MC) samples

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
File typeNameDescriptionLast modifiedSize# Events
root iconmc_105985.WW.rootDiboson process WW21-Jul-2016 16:0064,7Mb500000
root iconmc_105986.ZZ.rootDiboson process ZZ21-Jul-2016 16:0019,8Mb125000
root iconmc_105987.WZ.rootDiboson process WZ21-Jul-2016 16:0069,5Mb500000
root iconmc_110090.stop_tchan_top.rootSingle top t-channel top21-Jul-2016 16:0021,6Mb150000
root iconmc_110091.stop_tchan_antitop.rootsingle top t-channel antitop21-Jul-2016 16:0014,5Mb150000
root iconmc_110119.stop_schan.rootsingle top s-channel21-Jul-2016 16:0015,1Mb100000
root iconmc_110140.stop_wtchan.rootsingle top Wt-channel21-Jul-2016 16:0026,4Mb150000
root iconmc_110899.ZPrime400.rootZ' tt with MZ' = 400 GeV21-Jul-2016 16:004,4Mb21941
root iconmc_110901.ZPrime500.rootZ' tt with MZ' = 500 GeV21-Jul-2016 16:004,8Mb23231
root iconmc_110902.ZPrime750.rootZ' tt with MZ' = 750 GeV21-Jul-2016 16:005,4Mb25021
root iconmc_110903.ZPrime1000.rootZ' tt with MZ' = 1000 GeV21-Jul-2016 16:005,7Mb25525
root iconmc_110904.ZPrime1250.rootZ' tt with MZ' = 1250 GeV21-Jul-2016 16:005,6Mb25030
root iconmc_110905.ZPrime1500.rootZ' tt with MZ' = 1500 GeV21-Jul-2016 16:005,5Mb24142
root iconmc_110906.ZPrime1750.rootZ' tt with MZ' = 1750 GeV21-Jul-2016 16:005,2Mb23084
root iconmc_110907.ZPrime2000.rootZ' tt with MZ' = 2000 GeV21-Jul-2016 16:005,0Mb21997
root iconmc_110908.ZPrime2250.rootZ' tt with MZ' = 2250 GeV21-Jul-2016 16:004,8Mb21127
root iconmc_110909.ZPrime2500.rootZ' tt with MZ' = 2500 GeV21-Jul-2016 16:004,6Mb20327
root iconmc_110910.ZPrime3000.rootZ' tt with MZ' = 3000 GeV21-Jul-2016 16:004,4Mb19646
root iconmc_117049.ttbar_had.roottt Jets21-Jul-2016 16:005,8Mb25170
root iconmc_117050.ttbar_lep.roottt l + X21-Jul-2016 16:00300,1Mb1500000
root iconmc_147770.Zee.rootZee + Jets21-Jul-2016 16:00966,1Mb7500000
root iconmc_147771.Zmumu.rootZμμ + Jets21-Jul-2016 16:00946,4Mb7500000
root iconmc_147772.Ztautau.rootZττ + Jets21-Jul-2016 16:0095,8Mb750000
root iconmc_160155.ggH125_ZZ4lep.rootgg H ZZ 4l with MH = 125 GeV21-Jul-2016 16:0017,6Mb100000
root iconmc_160205.VBFH125_ZZ4lep.rootVBF H ZZ 4l with MH = 125 GeV21-Jul-2016 16:0019,4Mb100000
root iconmc_161005.ggH125_WW2lep.rootgg H WW llνν with MH = 125 GeV21-Jul-2016 16:0013,6Mb100000
root iconmc_161055.VBFH125_WW2lep.rootVBF H WW llνν with MH = 125 GeV21-Jul-2016 16:0015,4Mb100000
root iconmc_167740.WenuWithB.rootWeν + Jets with b21-Jul-2016 16:0088,0Mb750000
root iconmc_167741.WenuJetsBVeto.rootWeν + Jets with b veto21-Jul-2016 16:00305,4Mb2600000
root iconmc_167742.WenuNoJetsBVeto.rootWeν no Jets with b veto21-Jul-2016 16:00747,2Mb8000000
root iconmc_167743.WmunuWithB.rootWμν + Jets with b21-Jul-2016 16:0086,7Mb750000
root iconmc_167744.WmunuJetsBVeto.rootWμν + Jets with b veto21-Jul-2016 16:00296,1Mb2500000
root iconmc_167745.WmunuNoJetsBVeto.rootWμν no Jets with b veto21-Jul-2016 16:00689,2Mb7500000
root iconmc_167746.WtaunuWithB.rootWτν + Jets with b21-Jul-2016 16:0012,8Mb100000
root iconmc_167747.WtaunuJetsBVeto.rootWτν + Jets with b veto21-Jul-2016 16:0031,6Mb250000
root iconmc_167748.WtaunuNoJetsBVeto.rootWτν no Jets with b veto21-Jul-2016 16:0056,3Mb550000
root iconmc_173041.DYeeM08to15.rootDrell-Yan ee with Mee[08-15] GeV21-Jul-2016 16:0058,2Mb400000
root iconmc_173042.DYeeM15to40.rootDrell-Yan ee with Mee[15-40] GeV21-Jul-2016 16:00102,2Mb750000
root iconmc_173043.DYmumuM08to15.rootDrell-Yan μμ with Mμμ[08-15] GeV21-Jul-2016 16:0076,1Mb500000
root iconmc_173044.DYmumuM15to40.rootDrell-Yan μμ with Mμμ[15-40] GeV21-Jul-2016 16:00105,9Mb750000
root iconmc_173045.DYtautauM08to15.rootDrell-Yan ττ with Mττ[08-15] GeV21-Jul-2016 16:001,5Mb9993
root iconmc_173046.DYtautauM15to40.rootDrell-Yan ττ with Mττ[15-40] GeV21-Jul-2016 16:004,6Mb32393
+
+
+

Set of Data samples

+ + + + + + + + + + + + + + + + + + + + + + + + + +
File typeNameDescriptionLast modifiedSize# Events
root iconDataEgamma.rootATLAS 2012 data Egamma-string sample for 2016 open data release21-Jul-2016 16:00746,3Mb7917590
root iconDataMuons.rootATLAS 2012 data Muons-string sample for 2016 open data release21-Jul-2016 16:00619,8Mb7028084
+
+
+

Set of container files

+ + + + + + + + + + + + + + + +
File typeNameDescriptionLast modifiedSize
root iconcomplete_set_of_ATLAS_open_data_samples_July_2016.zipComplete set of Data and MonteCarlo samples into a single ZIP file21-Jul-2016 16:005,6Gb
+
+
+
+
+ +
+ +
+

Do you need help? Go to the documentation of this Level or its dedicated resource:

+

in GitBook

+
+ + + + + + + + + + + diff --git a/extendedanalysis/documentation.php b/extendedanalysis/documentation.php index 7a1bdaa..0f86e59 100644 --- a/extendedanalysis/documentation.php +++ b/extendedanalysis/documentation.php @@ -17,7 +17,7 @@
- +
diff --git a/extendedanalysis/index.php b/extendedanalysis/index.php index 9723b0b..94b3079 100644 --- a/extendedanalysis/index.php +++ b/extendedanalysis/index.php @@ -27,7 +27,10 @@
- Extended Analysis + Extended Analysis +
+ +
@@ -51,7 +54,7 @@
- +
diff --git a/extendedanalysis/software.php b/extendedanalysis/software.php index 4f3a453..935cd3d 100644 --- a/extendedanalysis/software.php +++ b/extendedanalysis/software.php @@ -16,11 +16,11 @@

You can download the complete software framework in a .ZIP file. Alternatively, download it from our dedicated - GitHub repository where you can also browse the files. + GitHub repository where you can also browse the files.

- Data & Tools - VMs + Data & Tools - software @@ -55,7 +55,7 @@

Software in GitHub

- + ATLAS to GitHub
@@ -68,10 +68,15 @@ Last modified Size + + python icon + python_framework_code_July_2016_V1.1.zip + 14-Jul-2016 10:00 + 44,0Kb + python icon python_framework_code_June_2016_V1.0.zip - 08-Jun-2016 20:00 44,0Kb diff --git a/header.html b/header.html index 35fbcb8..aff6533 100644 --- a/header.html +++ b/header.html @@ -222,3 +222,14 @@

ATLAS + + + + + + diff --git a/index.php b/index.php index 0b847f5..9e492b0 100644 --- a/index.php +++ b/index.php @@ -15,7 +15,7 @@
- +
diff --git a/terms-of-use.php b/terms-of-use.php index ee613e6..4e5aaec 100644 --- a/terms-of-use.php +++ b/terms-of-use.php @@ -10,30 +10,32 @@

Terms of Use

- The data is made available under the CC0 public domain dedication and is therefore not subject to usage restrictions. However, please note that the data and Monte Carlo presented are explicitly processed for educational uses. - These data are not used for ATLAS analysis. They have been uniquely processed to reduce significantly the complexity of the data, and time for the processing, so that it can be used easily for educational uses. (ADD GENERAL DISCLAIMER AND LIMITATION ON LIABILITY) + The data is made available under the CC0 public domain dedication and is therefore not subject to usage restrictions. However, please note that the data and Monte Carlo presented are explicitly processed for educational uses. + These data are not used for ATLAS analysis. They have been uniquely processed to reduce significantly the complexity of the data, and time for the processing, so that it can be used easily for educational uses.

+

+ Neither the authors of this website, its components and resources (datasets, apps and software), nor their employing institutes, nor the agencies providing financial support for this work make any representation or warranty, explicitly or implicitly, regarding this this website, its components and resources (datasets, apps and software) or assume any liability for its use. +

+

You are free to use ATLAS imagery, video and audio material for educational, scientific, or informational purposes (including photo collections, textbooks, public exhibits and Web pages) provided the copyright is shown as follows: -
-
+

ATLAS Experiment © 2016 CERN -
-
+

ATLAS images are under CERN copyright. If the ATLAS material is to be used for commercial purposes, it must not explicitly or implicitly convey CERN or ATLAS' endorsement.

-
-
-
+ +
+
- - - - - + + + + + - - + + diff --git a/visualisations/JsRoot460/LICENSE b/visualisations/JsRoot460/LICENSE new file mode 100644 index 0000000..e18084b --- /dev/null +++ b/visualisations/JsRoot460/LICENSE @@ -0,0 +1,21 @@ +The MIT License + +Copyright 2013-2015 JavaScript ROOT authors + +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 THE +AUTHORS OR COPYRIGHT HOLDERS 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. diff --git a/visualisations/JsRoot460/changes.md b/visualisations/JsRoot460/changes.md new file mode 100644 index 0000000..5f95719 --- /dev/null +++ b/visualisations/JsRoot460/changes.md @@ -0,0 +1,489 @@ +# JSROOT changelog + +## Changes in 4.6.0 +1. Improvements in TGeo drawings + - support of large (~10M volumes) models, only most significant volumes are shown + - one could activate several clip planes (only with WebGL) + - interaction with object browser to change visibility flags or focus on selected volume + - support of floating browser for TGeo objects + - intensive use of HTML Worker to offload computation tasks and keep interactivity + - enable more details when changing camera position/zoom + - better and faster build of composite shapes +2. Improvements in histograms 3D drawing + - all lego options: lego1..lego4, combined with 'fb', 'bb', '0' or 'z' + - support axis lebels on lego plots + - support lego plots for TH1 +3. Improvements in all 3D graphics + - upgrafe three.js to r79 + - use of THREE.BufferGeometry for all components + - significant (up to factor 10) performance improvement +4. Implement box and hbox draw options for TH1 class +5. Implement drawing of axes ticks on opposite side (when fTickx/y specified) +6. Preliminary support of candle plot (many options to be implemented) +7. Update draw attributes (fill/line/position) when monitor objects + + +## Changes in 4.5.3 +1. Fix - position of TFrame in canvas/pad +2. Fix - use histogram fMinimum/fMaximum when creating color palette +3. Fix - correctly draw empty th2 bins when zmin<0 is specified +4. Fix - limit th2 text output size +5. Fix - use histogram fMinimum/fMaximum when drawing z axis in lego plot +6. Fix - error in TGeoCtub shape creation +7. Fix - error in pcon/pgon shapes when Rmin===0 + + +## Changes in 4.5.1 +1. Fix - correctly handle ^2..^9 in TFormula equations +2. Fix - support TMath::Gaus in TFormula +3. Fix - correctly display ^2 and ^3 in SVG text output +4. Fix - do not show tooltips for empty TProfile bins +5. Fix - statbox toggling was not working on subpads +6. Fix - positioning of 3D objects in Webkit browsers in complex layouts +7. Fix - difference in TF1 between ROOT5/6 (#54) + + +## Changes in 4.5.0 +1. Zooming with mouse wheel +2. Context menus for many different objects attributes are provided +3. Context menu for every drawn object can be activated via toolbar button +4. Support browsing of TTask and derived classes (#40) +5. Apply user range for drawing TH1/TH2 histograms, also when superimposed (#44) +6. Implement scaling factor like x10^3 on the vertical axes +7. Provide shortcut buttons for each subpad +8. Implement simple drawing for TBox, TWbox, TSliderBox classes + + +## Changes in 4.4.4 +1. Fix - toggling of statbox was not working in all situations +2. Fix - for mouse rect zooming use only left mouse button +3. Fix - correctly draw TH2 with lego option, when histogram has negative bin content +4. Fix - log axis drawing with no visible ticks + + +## Changes in 4.4.3 +1. Fix - wrong selection of TH1 Y axis range when errors are displayed (#44) +2. Fix - apply user range for TH1 X-axis zooming (#44) +3. Fix - protect against pathological case of 1-bin histogram +4. Fix - use error plot by default in TH1 only when positive sumw2 entry exists +5. Fix - for TH2 box draw option draw at least 1px rect for non-empty bin +6. Fix - support transparency (alpha) in TColor (#45) +7. Fix - correct tooltip handling for graphs with lines and markers +8. Fix - interactive zooming in TH2 when doing histogram update + + +## Changes in 4.4.2 +1. Fix - statistic collection for TH2 +2. Fix - correct handling of empty TList in browser/inspector +3. Fix - support TFolder in browser/inspector (#40) + + +## Changes in 4.4.1 +1. Fix - colz palette resize when drawing histogram second time +2. Fix - use embeded in TCanvas color for background color of canvas itself +3. Fix - rotate too long X axis text labels +4. Fix - draw histogram bins on frame boundary +5. Fix - use alternative color for shapes with default black color +6. Fix - correctly handle pcon/pgon shape with rmin==rmax on top or bottom side + + +## Changes in 4.4 +1. Fix faces orientation for all TGeo shapes. +2. Improve TGeoTorus creation - handle all parameters combinations +3. Implement TGeoCompositeShape, using ThreeCSG.js +4. Fix problem with color pallete when switch to 3D mode (#28) +5. Use nested CSS classes to avoid conflicts with other libraries (#29) +6. Let move and resize TFrame +7. Improve TH1/TH2 drawings + - draw all histograms points in the range (no any skipped bins) + - minimize SVG code for drawing (up to factor 100) + - gives significant speedup in drawings +8. SVG code improvement for TGraph, TF1, TAxis drawings +9. Provide new tooltip kind + - created only when needed (minimizing SVG code) + - tooltip can be drawn for every object in the frame + - touch devices are supported +10. Fix - let draw same object on the canvas with different options +11. Create cached list of known class methods. It can be extended by users. +12. Use of cached methods improves binary I/O perfromance by 20% +13. Support TGaxis +14. Project now can be obtained via 'bower install jsroot' +15. Support 'scat' and 'text' draw options for TH2 +16. Support in binary I/O zipped buffer bigger than 16M +17. Correctly handle in binary I/O pointer on TArray object (like in THnSparseArrayChunk) + + +## Changes in 4.3 +1. Implement TGeoCtub, TGeoParaboloid and TGeoHype shapes +2. Support TGeoTube with Rmin==0 +3. Exclude empty faces in TGeoArb8 +4. Improve TGeoSphere creation - handle all parameters combinations +5. Introduce JSROOT.cleanup() function to safely clear all drawn objects +6. Fix wrong resize method in 'tabs' and 'collapsible' layouts +7. Fix canvas resize problem (issue #27) +8. Fix zero-height canvas when draw TGeo in collapsible layout +9. Fix problem of simultaneous move TGeo drawings and canvas in flexible layout + + +## Changes in 4.2 +1. Significant performance improvements in 3D drawings - TGeo/TH2/TH3 +2. Implement TGeoPara, TGeoGtra, TGeoXtru and TGeoEltu shapes +3. Optimize (reduce vertices number) for others TGeo shapes +4. Correct rotation/translation/scaling of TGeo nodes +5. Workaround for axis reflection (not directly supported in three.js) +6. Support array of objects in I/O (like in TAxis3D) +7. Correct reading of multi-dim arrays like Double_t fXY[8][2]; +8. Provide canvas toolbar for actions like savepng or unzoom +9. Implement JSROOT.resize() function to let resize drawing after changes in page layout +10. Fix error with title display/update + + +## Changes in 4.1 +1. Introduce object inspector - one could browse object members of any class +2. Let draw sub-items from TCanvas list of primitives like sub-pad or TLatex +3. Provide possibility to save drawn SVG canvas as PNG +4. TGraph drawing optimization - limit number of drawn points +5. Implement painter for TPolyMarker3D +6. Improve drawing and update of TMultiGraph +7. Reorganize 3D drawing of TH2/TH3 histograms, allow to mix 2D and 3D display together +8. Support overlay of 3D graphic over SVG canvas (used for IE) +9. Fix problems and improve flex(ible) layout + + +## Changes in 4.0 +1. New TGeo classes support: + - browsing through volumes hieararchy + - changing visibility flags + - drawing of selected volumes +2. New 'flex' layout: + - create frames like in Multi Document Interface + - one could move/resize/minimize/maximize such frames +3. Significant (factor 4) I/O performance improvement: + - use ArrayBuffer class in HTTP requests instead of String + - use native arrays (like Int32Array) for array data members + - highly optimize streamer infos handling +4. TH2 drawing optimization: + - if there are too many non-empty bins, combine them together + - when zoom-in, all original bins will be displayed separately + - let draw big TH2 histogram faster than in 1 sec + - optimization can be disabled by providing '&optimize=0' in URL +5. TF1 drawing optimization: + - function 'compiled' only once +6. Reorganize scripts structure: + - move all math functions to JSRootMath.js + - TH2, TF1, THStack and TMultiGraph painters moved into JSRootPainter.more.js script + - reduce size of scripts required for default functionality +7. Update all basic libraries: + - d3.js - v3.5.9, + - jquery.js - v2.1.4, + - jquery-ui.js - v1.11.4, + - three.js - r73 +8. Implement ROOT6-like color palettes: + - all palettes in range 51...112 are implemented + - by default palette 57 is used + - one could change default palette with '&palette=111' in URL + - or palette can be specified in draw option like '&opt=colz,pal77' + + +## Changes in 3.9 +1. Support non-equidistant bins for TH1/TH2 objects. +2. Display entries count from histo.fEntries member, only when not set use computed value +3. Support italic and bold text when used with MathJax +4. Improve TF1 drawing - support exp function in TFormula, fix errors with logx scale, enable zoom-in, (re)calculate function points when zooming +5. Support several columns in TLegend +6. Introduce context menus for x/y axis, add some items similar to native ROOT menus +7. Introduce context menu for TPaveStats, let switch single elements in the box +8. Enable usage of all context menus on touch devices +9. Implement JSROOT.Math.Prob function, provides probability value in stat box +10. Introduce context menu for color palette (z axis) +11. Implement col0 and col0z draw option for TH2 histograms, similar to ROOT6 + + +## Changes in 3.8 +1. Let use HTML element pointer in JSROOT.draw function like: + JSROOT.draw(document.getElementsByTagName("div")[0], obj, "hist"); + Normally unique identifier was used before, which is not required any longer. + Of course, old functionality with element identifier will work as well. +2. TreePlayer can also be used for trees, which not yet read from the file. + Requires appropriate changes in TRootSniffer class. +3. Fix error in I/O with members like: `Double_t *fArr; //[fN]` +4. Introduce JSROOT.OpenFile function. It loads I/O functionality automatically, + therefore can be used directly after loading JSRootCore.js script +5. Same is done with JSROOT.draw function. It is defined in the JSRootCore.js + and can be used directly. Makes usage of JSROOT easier +6. Introduce JSRootPainter.more.js script, where painters for auxiliary classes + will be implemented. +7. Implement painter for TEllipse, TLine, TArrow classes +8. Fix several problems with markers drawing; implement plus, asterisk, mult symbols. +9. Implement custom layout, which allows to configure user-defined layout for displayed objects +10. Fix errors with scaling of axis labels. +11. Support also Y axis with custom labels like: http://jsroot.gsi.de/dev/?nobrowser&file=../files/atlas.root&item=LEDShapeHeightCorr_Gain0;1&opt=col + + +## Changes in 3.7 +1. Support of X axis with custom labels like: http://jsroot.gsi.de/dev/index.htm?nobrowser&json=../files/hist_xlabels.json +2. Extend functionality of JSROOT.addDrawFunc() function. One could register type-specific + `make_request` and `after_request` functions; `icon`, `prereq`, `script`, `monitor` properties. + This let add more custom elements to the generic gui, implemented with JSROOT.HierarchyPainter +3. Provide full support of require.js. One could load now JSRootCore.js script like: + + + + After this several modules are defined and can be used with syntax like: + + require(['JSRootPainter'], function(jsroot) { /*any user code*/}); + + Also inside JSROOT require.js used to load all dependencies. + + +## Changes in 3.6 +1. Try to provide workaround for websites where require.js already loaded. + This makes problem by direct loading of jquery and jquery-ui +2. Provide workaround for older version of jquery-ui +3. Prompt for input of command arguments +4. After command execution one could automatically reload hierarchy (_hreload property) or + update view of displayed object (_update_item property) +5. Use HiearchyPainter for implementing draw.htm. This let us handle + all different kinds of extra attributes in central place +6. Fix problem in tabs layout - new tab should be add to direct child +7. When drawing several tabs, activate frame before drawing - only then + real frame size will be set +8. Fix problem with GetBBox - it only can be used for visible elements in mozilla. +9. Support drawing of fit parameters in stat box, use (as far as possible) stat and + fit format for statistic display +10. Implement 'g' formatting kind for stat box output - one need to checks + significant digits when producing output. +11. Support new draw options for TGraph: 'C', 'B1', '0', '2', '3', '4', '[]' +12. Primary support for STL containers in IO part. Allows to read ROOT6 TF1. +13. Full support of TGraphBentErrors +14. Support objects drawing from JSON files in default user interface, including + monitoring. One could open file from link like: https://root.cern.ch/js/dev/?json=demo/canvas_tf1.json +15. Introduce JSROOT.FFormat function to convert numeric values into string according + format like 6.4g or 5.7e. Used for statistic display. + + +## Changes in 3.5 +1. Fix error in vertical text alignment +2. Many improvements in TPaletteAxis drawing - draw label, avoid too large ticks. +3. Fix error with col drawing - bin with maximum value got wrong color +4. Test for existing jquery.js, jquery-ui.js and d3.js libraries, reuse when provided +5. Fix several I/O problems; now one could read files, produced in Geant4 +6. Implement 'e2' drawing option for TH1 class, + use by default 'e' option when TH1 has non-empty fSumw2 +7. Reuse statistic from histogram itself, when no axis selection done +8. Support log/lin z scale for color drawing +9. Implement interactive z-scale selection on TPaletteAxis +10. Allow to redraw item with other draw options (before one should clear drawings) +11. Several improvements in THttpServer user interface - repair hierarchy reload, + hide unsupported context menu entries, status line update + + +## Changes in 3.4 +1. Support usage of minimized versions of .js and .css files. + Minimized scripts used by default on web servers. +2. Implement JSROOT.extend instead of jQuery.extend, reduce + usage of jquery.js in core JSROOT classes +3. Implement main graphics without jquery at all, + such mode used in `nobrowser` mode. +4. Provide optional latex drawing with MathJax SVG. + TMathText always drawn with MathJax, + other classes require `mathjax` option in URL +5. Improve drawing of different text classes, correctly handle + their alignment and scaling, special handling for IE +6. Fix error with time axes - time offset was not correctly interpreted + + +## Changes in 3.3 +1. Use d3.time.scale for display of time scales +2. Within JSRootCore.js script URL one could specify JSROOT + functionality to be loaded: '2d', '3d', 'io', 'load', 'onload'. + Old method with JSROOT.AssertPrerequisites will also work. +3. With THttpServer JSROOT now provides simple control functionality. + One could publish commands and execute them from the browser +4. One could open several ROOT files simultaneously +5. Add 'simple' layout - drawing uses full space on the right side +6. Allow to open ROOT files in online session (via url parameter) +7. One could monitor simultaneously objects from server and root files +8. Implement 'autocol' draw option - when superimposing histograms, + their line colors will be automatically assigned +9. Implement 'nostat' draw option - disabled stat drawing +10. Using '_same_' identifier in item name, one can easily draw or superimpose + similar items from different files. Could be used in URL like: + `...&files=[file1.root,file2.root]&items=[file1.root/hpx, file2.root/_same_]` + `...&files=[file1.root,file2.root]&item=file1.root/hpx+file2.root/_same_` + Main limitation - file names should have similar length. +11. When 'autozoom' specified in draw options, histogram zoomed into + non-empty content. Same command available via context menu. +12. Item of 'Text' kind can be created. It is displayed as + plain text in the browser. If property 'mathjax' specified, + MathJax.js library will be loaded and used for rendering. + See httpcontrol.C macro for example. +13. When using foreignObject, provide workaround for absolute positioning + problem in Chrome/Safari, see + + +## Changes in 3.2 +1. Support JSON objects embedding in html pages, produced by THttpServer +2. For small resize of canvas use autoscale functionality of SVG. Only when + relative changes too large, redraw complete canvas again. +3. Use touch-punch.min.js to process touch events with jquery-ui +4. Even when several TH1/TGraph/TF1 objects with fill attribute overlap each other, + one able to get tooltip for underlying objects +5. Use jquery-ui menu for context menu +6. From context menu one could select several options for drawing +7. Provide user interface for executing TTree::Draw on THttpServer +8. 3D graphic (three.js) works only with IE11 + + +## Changes in 3.1 +1. Correctly show tooltips in case of overlapped objects +2. Implement JSROOT.Create() method to create supported + in JavaScript ROOT classes like TH1 or TGraph +3. Fix problem with JSROOT.draw in HTML element with zero width (display:none) +4. Provide possibility to load user scripts with JSROOT.BuildSimpleGUI + and JSROOT.AssertPrerequisites, also with main index.htm +5. Support of TCutG drawing +6. Implement hierarchy display (former dtree) with jQuery +7. Fix several problems in drawing optimization +8. Implement dragging objects from hierarchy browser into existing canvas + to superimpose several objects +9. Implement col2 and col3 draw options, using html5 canvas +10. Support 'p' and 'p0' draw options for TH1 class + + +## Development of version 3.0 + +### November 2014 +1. Better font size and position in pave stats +2. Resize/move of element only inside correspondent pad +3. Adjust of frame size when Y-axis exceed pad limits +4. Correct values in tooltip for THStack +5. Exclude drawing of markers from TGraph outside visible range +6. Drawing of canvas without TFrame object +7. Many other small bug fixes and improvements, thanks to Maximilian Dietrich + +### October 2014 +1. Add "shortcut icon" +2. Add demo of online THttpServer - shell script copies data from + running httpserver.C macro on Apache webserver +3. Evaluate 'monitoring' parameter for online server like: + + Parameter defines how often displayed objects should be updated. +4. Implement 'opt' and 'opts' URL parameters for main page. +5. Show progress with scripts loading in the browser window +6. When one appends "+" to the filename, its content read completely with first I/O operation. +7. Implement JS custom streamer for TCanvas, restore aspect ratio when drawing +8. Major redesign of drawing classes. Resize and update of TCanvas are implemented. + All major draw functions working with HTML element id as first argument. +9. Extract 3D drawings into separate JSRoot3DPainter.js script +10. Use newest three.min.js (r68) for 3D drawings, solves problem with Firefox. +11. Introduce generic list of draw functions for all supported classes. +12. Add possibility to 'expand' normal objects in the hierarchy browser. + For instance, this gives access to single elements of canvas, + when whole canvas cannot be drawn. +13. Correct usage of colors map, provided with TCanvas. +14. Introduce JSROOT.redraw() function which is capable to create or update object drawing. +15. In main index.htm page browser can be disabled (nobrowser parameter) and + page can be used to display only specified items from the file +16. Add support of TPolyMarker3D in binary I/O + +### September 2014 +1. First try to handle resize of the browser, + for the moment works only with collapsible layout +2. Also first try to interactively move separation line between + browser and drawing field. +3. Small fix of minor ticks drawing on the axis +4. Introduce display class for MDI drawing. Provide two implementations - + 'collapsible' for old kind and 'tabs' for new kinds. +5. Adjust size of color palette drawing when labels would take more place as provided. +6. Add correct filling of statistic for TProfile, + fix small problem with underflow/overflow bins. +7. Provide way to select display kind ('collapsible', 'tabs') in the simple GUI. +8. Implement 'grid' display, one could specify any number of devision like + 'grid 3x3' or 'grid 4x2'. +9. MDI display object created at the moment when first draw is performed. +10. Introduce painter class for TCanvas, support resize and update of canvas drawing +11. Resize almost works for all layouts and all objects kinds. +12. Implement JSROOT.GetUrlOption to extract options from document URL. +13. Provide example fileitem.htm how read and display item from ROOT file. +14. In default index.htm page one could specify 'file', 'layout', + 'item' and 'items' parameters like: + +15. Support direct reading of objects from sub-sub-directories. +16. Introduce demo.htm, which demonstrates online usage of JSROOT. +17. One could use demo.htm directly with THttpServer providing address like: + +18. Also for online server process url options like 'item', 'items', 'layout' +19. Possibility to generate URL, which reproduces opened page with layout and drawn items + +### August 2014 +1. All communication between server and browser done with JSON format. +2. Fix small error in dtree.js - one should always set + last sibling (_ls) property while tree can be dynamically changed. +3. In JSRootCore.js provide central function, which handles different kinds + of XMLHttpRequest. Use only async requests, also when getting file header. +4. Fully reorganize data management in file/tree/directory/collection hierarchical + display. Now complete description collected in HPainter class and decoupled from + visualization, performed with dTree.js. +5. Remove all global variables from the code. +6. Automatic scripts/style loading handled via JSROOT.loadScript() function. + One can specify arbitrary scripts list, which asynchronously loaded by browser. +7. Method to build simple GUI changed and more simplified :). The example in index.htm. + While loadScript and AssertPrerequisites functions moved to JSROOT, one + can easily build many different kinds of GUIs, reusing provided JSRootCore.js functions. +8. In example.htm also use AssertPrerequisites to load necessary scripts. + This helps to keep code up-to-date even by big changes in JavaScript code. +9. Provide monitoring of online THttpServer with similar interface as for ROOT files. +10. Fix several errors in TKey Streamer, use member names as in ROOT itself. +11. Keep the only version identifier JSROOT.version for JS code +12. One can specify in JSROOT.AssertPrerequisites functionality which is required. + One could specify '2d', 'io' (default) or '3d'. +13. Use new AssertPrerequisites functionality to load only required functionality. +14. When displaying single element, one could specify draw options and monitor property like: + + Such link is best possibility to integrate display into different HTML pages, + using `` +15. Remove 'JSROOTIO.' prefix from _typename. Now real class name is used. +16. Use in all scripts JSROOT as central 'namespace' +17. Introduce context menu in 3D, use it for switch between 2D/3D modes +18. Use own code to generate hierarchical structure in HTML, replace dtree.js which is + extremely slow for complex hierarchies. Dramatically improve performance for + structures with large (~1000) number of items. +19. Deliver to the server title of the objects, display it as hint in the browser. +20. Better handling of special characters in the hierarchies - allows to display + symbols like ' or " in the file structure. + +### July 2014 +1. Migration to d3.v3.js and jQuery v2.1.1 +2. Fix errors in filling of histogram statbox +3. Possibility of move and resize of statbox, title, color palete +4. Remove many (not all) global variables +5. Example with direct usage of JSRootIO graphics +6. Example of inserting ROOT graphics from THttpServer into `` + +### May 2014 +1. This JSRootIO code together with THttpServer class included + in ROOT repository + +### March 2014 +1. Introduce JSROOT.TBuffer class, which plays similar role + as TBuffer in native ROOT I/O. Simplifies I/O logic, + reduce duplication of code in many places, fix errors. + Main advantage - one could try to keep code synchronous with C++. +2. Avoid objects cloning when object referenced several times. +3. Treat special cases (collection, arrays) in one place. + This is major advantage, while any new classes need to be implemented only once. +4. Object representation, produced by JSRootIO is similar to + objects, produced by TBufferJSON class. By this one can exchange + I/O engine and use same JavaSctript graphic for display. +5. More clear functions to display different elements of the file. + In the future functions should be fully separated from I/O part + and organized in similar way as online part. +6. Eliminate usage of gFile pointer in the I/O part. +7. Provide TBufferJSON::JsonWriteMember method. It allows to stream any + selected data member of the class. Supported are: + basic data types, arrays of basic data types, TString, TArray classes. + Also any object as data member can be streamed. +8. TRootSniffer do not creates sublevels for base classes diff --git a/visualisations/JsRoot460/img/RootIcon.ico b/visualisations/JsRoot460/img/RootIcon.ico new file mode 100644 index 0000000..8bce131 Binary files /dev/null and b/visualisations/JsRoot460/img/RootIcon.ico differ diff --git a/visualisations/JsRoot460/index.htm b/visualisations/JsRoot460/index.htm new file mode 100644 index 0000000..f0c27cd --- /dev/null +++ b/visualisations/JsRoot460/index.htm @@ -0,0 +1,149 @@ + + + + + Read an ATLAS ROOT file + + + + + + +
+ + + loading scripts :) ... +
+ + + + diff --git a/visualisations/JsRoot460/indexr.htm b/visualisations/JsRoot460/indexr.htm new file mode 100644 index 0000000..e9e35f7 --- /dev/null +++ b/visualisations/JsRoot460/indexr.htm @@ -0,0 +1,48 @@ + + + + + Read a ROOT file + + + + + + +
+ loading scripts ... +
+ + + + diff --git a/visualisations/JsRoot460/scripts/JSRoot3DPainter.js b/visualisations/JsRoot460/scripts/JSRoot3DPainter.js new file mode 100644 index 0000000..f011de7 --- /dev/null +++ b/visualisations/JsRoot460/scripts/JSRoot3DPainter.js @@ -0,0 +1,2114 @@ +/// @file JSRoot3DPainter.js +/// JavaScript ROOT 3D graphics + +(function( factory ) { + if ( typeof define === "function" && define.amd ) { + // AMD. Register as an anonymous module. + define( ['d3', 'JSRootPainter', 'threejs_all'], factory ); + } else { + + if (typeof JSROOT == 'undefined') + throw new Error('JSROOT is not defined', 'JSRoot3DPainter.js'); + + if (typeof d3 != 'object') + throw new Error('This extension requires d3.v3.js', 'JSRoot3DPainter.js'); + + if (typeof JSROOT.Painter != 'object') + throw new Error('JSROOT.Painter is not defined', 'JSRoot3DPainter.js'); + + if (typeof THREE == 'undefined') + throw new Error('THREE is not defined', 'JSRoot3DPainter.js'); + + factory(d3, JSROOT); + } +} (function(d3, JSROOT) { + + JSROOT.Painter.TestWebGL = function() { + // return true if WebGL should be used + /** + * @author alteredq / http://alteredqualia.com/ + * @author mr.doob / http://mrdoob.com/ + */ + + if (JSROOT.gStyle.NoWebGL) return false; + + if ('_Detect_WebGL' in this) return this._Detect_WebGL; + + try { + var canvas = document.createElement( 'canvas' ); + this._Detect_WebGL = !! ( window.WebGLRenderingContext && ( canvas.getContext( 'webgl' ) || canvas.getContext( 'experimental-webgl' ) ) ); + //res = !!window.WebGLRenderingContext && !!document.createElement('canvas').getContext('experimental-webgl'); + } catch (e) { + return false; + } + + return this._Detect_WebGL; + } + + JSROOT.Painter.TooltipFor3D = function(prnt, canvas) { + this.tt = null; + this.cont = null; + this.lastlbl = ''; + this.parent = prnt ? prnt : document.body; + this.canvas = canvas; // we need canvas to recalculate mouse events + this.abspos = !prnt; + + this.pos = function(e) { + // method used to define position of next tooltip + // event is delivered from canvas, + // but position should be calculated relative to the element where tooltip is placed + + if (this.tt === null) return; + var u,l; + if (this.abspos) { + l = JSROOT.browser.isIE ? (e.clientX + document.documentElement.scrollLeft) : e.pageX; + u = JSROOT.browser.isIE ? (e.clientY + document.documentElement.scrollTop) : e.pageY; + } else { + + l = e.offsetX; + u = e.offsetY; + + var rect1 = this.parent.getBoundingClientRect(), + rect2 = this.canvas.getBoundingClientRect(); + + if ((rect1.left !== undefined) && (rect2.left!== undefined)) l += (rect2.left-rect1.left); + + if ((rect1.top !== undefined) && (rect2.top!== undefined)) u += rect2.top-rect1.top; + + if (l + this.tt.offsetWidth + 3 >= this.parent.offsetWidth) + l = this.parent.offsetWidth - this.tt.offsetWidth - 3; + + if (u + this.tt.offsetHeight + 15 >= this.parent.offsetHeight) + u = this.parent.offsetHeight - this.tt.offsetHeight - 15; + + // one should find parent with non-static position, + // all absolute coordinates calculated relative to such node + var abs_parent = this.parent; + while (abs_parent) { + // console.log(abs_parent.nodeType, abs_parent.id); + var style = getComputedStyle(abs_parent); + if (!style || (style.position !== 'static')) break; + if (!abs_parent.parentNode || (abs_parent.parentNode.nodeType != 1)) break; + abs_parent = abs_parent.parentNode; + } + + if (abs_parent && (abs_parent !== this.parent)) { + var rect0 = abs_parent.getBoundingClientRect(); + l+=(rect1.left - rect0.left); + u+=(rect1.top - rect0.top); + } + + } + + this.tt.style.top = (u + 15) + 'px'; + this.tt.style.left = (l + 3) + 'px'; + }; + + this.show = function(v) { + if (JSROOT.gStyle.Tooltip <= 0) return; + if (!v || v==="") return this.hide(); + + if (this.tt === null) { + this.tt = document.createElement('div'); + this.tt.setAttribute('class', 'jsroot'); + var t = document.createElement('div'); + t.setAttribute('class', 'tt3d_border'); + this.cont = document.createElement('div'); + this.cont.setAttribute('class', 'tt3d_cont'); + var b = document.createElement('div'); + b.setAttribute('class', 'tt3d_border'); + this.tt.appendChild(t); + this.tt.appendChild(this.cont); + this.tt.appendChild(b); + this.tt.style.opacity = 1; + this.tt.style.filter = 'alpha(opacity=1)'; + this.tt.style.position = 'absolute'; + this.tt.style.display = 'block'; + this.tt.style.overflow = 'hidden'; + this.parent.appendChild(this.tt); + } + + if (this.lastlbl !== v) { + this.cont.innerHTML = v; + this.lastlbl = v; + this.tt.style.width = 'auto'; // let it be automatically resizing... + if (JSROOT.browser.isIE) + this.tt.style.width = this.tt.offsetWidth; + } + }; + + this.hide = function() { + if (this.tt !== null) + this.parent.removeChild(this.tt); + + this.tt = null; + this.lastlbl = ""; + } + + return this; + } + + + JSROOT.Painter.CreateOrbitControl = function(painter, camera, scene, renderer, lookat) { + var control = new THREE.OrbitControls(camera, renderer.domElement); + + control.enableDamping = false; + control.dampingFactor = 1.0; + control.enableZoom = true; + if (lookat) { + control.target.copy(lookat); + control.target0.copy(lookat); + control.update(); + } + + var mouse_ctxt = { x:0, y: 0, on: false }, + raycaster = new THREE.Raycaster(), + webgl = renderer instanceof THREE.WebGLRenderer, + control_active = false, + control_changed = false, + block_ctxt = false, // require to block context menu command appearing after control ends, required in chrome which inject contextmenu when key released + tooltip = new JSROOT.Painter.TooltipFor3D(painter.select_main().node(), renderer.domElement); + + control.ProcessMouseDblclick = function() { + control.reset(); + // painter.Render3D(); + } + + control.HideTooltip = function() { + tooltip.hide(); + } + + function GetMousePos(evnt, mouse) { + mouse.x = ('offsetX' in evnt) ? evnt.offsetX : evnt.layerX; + mouse.y = ('offsetY' in evnt) ? evnt.offsetY : evnt.layerY; + mouse.clientX = evnt.clientX; + mouse.clientY = evnt.clientY; + return mouse; + } + + function GetIntersects(mouse) { + // domElement gives correct coordinate with canvas render, but isn't always right for webgl renderer + var sz = webgl ? renderer.getSize() : renderer.domElement; + var pnt = { x: mouse.x / sz.width * 2 - 1, y: -mouse.y / sz.height * 2 + 1 }; + + camera.updateMatrix(); + camera.updateMatrixWorld(); + raycaster.setFromCamera( pnt, camera ); + var intersects = raycaster.intersectObjects(scene.children, true); + + // painter may want to filter intersects + if (typeof painter.FilterIntersects == 'function') + intersects = painter.FilterIntersects(intersects); + + return intersects; + } + + control.addEventListener( 'change', function() { + mouse_ctxt.on = false; // disable context menu if any changes where done by orbit control + painter.Render3D(0); + control_changed = true; + }); + + control.addEventListener( 'start', function() { + control_active = true; + block_ctxt = false; + mouse_ctxt.on = false; + + tooltip.hide(); + + // do not reset here, problem of events sequence in orbitcontrol + // it issue change/start/stop event when do zooming + // control_changed = false; + }); + + control.addEventListener( 'end', function() { + control_active = false; + if (mouse_ctxt.on) { + mouse_ctxt.on = false; + control.ContextMenu(mouse_ctxt, GetIntersects(mouse_ctxt)); + // painter.OrbitContext(mouse_ctxt, GetIntersects(mouse_ctxt)); + } else + if (control_changed) { + // react on camera change when required + } + control_changed = false; + }); + + function control_contextmenu(evnt) { + evnt.preventDefault(); + GetMousePos(evnt, mouse_ctxt); + if (control_active) + mouse_ctxt.on = true; + else + if (block_ctxt) + block_ctxt = false; + else + control.ContextMenu(mouse_ctxt, GetIntersects(mouse_ctxt)); + + // console.log('call context menu'); + // painter.OrbitContext(mouse_ctxt, GetIntersects(mouse_ctxt)); + }; + + function control_touchstart(evnt) { + if (!evnt.touches) return; + + // disable context menu if any changes where done by orbit control + if (!control_changed && !mouse_ctxt.touchtm) { + GetMousePos(evnt.touches[0], mouse_ctxt); + mouse_ctxt.touchtm = new Date().getTime(); + } + }; + + function control_touchend(evnt) { + if (!evnt.touches) return; + + if (control_changed || !mouse_ctxt.touchtm) return; + + var diff = new Date().getTime() - mouse_ctxt.touchtm; + delete mouse_ctxt.touchtm; + if (diff < 200) return; + + var pos = GetMousePos(evnt.touches[0], {}); + + if ((Math.abs(pos.x - mouse_ctxt.x) <= 10) && (Math.abs(pos.y - mouse_ctxt.y) <= 10)) + control.ContextMenu(mouse_ctxt, GetIntersects(mouse_ctxt)); + }; + + control.ContextMenu = function(pos, intersects) { + // do nothing, function called when context menu want to be activated + } + + function control_mousemove(evnt) { + if (control_active && evnt.buttons && (evnt.buttons & 2)) { + block_ctxt = true; // if right button in control was active, block next context menu + } + + if (control_active || !control.ProcessMouseMove) return; + + var mouse = GetMousePos(evnt, {}); + evnt.preventDefault(); + + var intersects = GetIntersects(mouse); + + var info = control.ProcessMouseMove(intersects); + + if (info && (info.length>0)) { + tooltip.show(info, 200); + tooltip.pos(evnt) + } else { + tooltip.hide(); + } + + // console.log('provide tooltip', intersects.length); + }; + + function control_mouseleave() { + tooltip.hide(); + if (control.ProcessMouseLeave) control.ProcessMouseLeave(); + }; + + renderer.domElement.addEventListener( 'dblclick', function() { control.ProcessMouseDblclick(); }); + + renderer.domElement.addEventListener('contextmenu', control_contextmenu); + renderer.domElement.addEventListener('mousemove', control_mousemove); + renderer.domElement.addEventListener('mouseleave', control_mouseleave); + + // do not use touch events, context menu should be activated via button + //painter.renderer.domElement.addEventListener('touchstart', control_touchstart); + //painter.renderer.domElement.addEventListener('touchend', control_touchend); + + + return control; + } + + JSROOT.Painter.DisposeThreejsObject = function(obj) { + if (!obj) return; + + if (obj.children) { + for (var i = 0; i < obj.children.length; i++) + JSROOT.Painter.DisposeThreejsObject(obj.children[i]); + obj.children = undefined; + } + if (obj.geometry) { + obj.geometry.dispose(); + obj.geometry = undefined; + } + if (obj.material) { + if (obj.material.map) { + obj.material.map.dispose(); + obj.material.map = undefined; + } + obj.material.dispose(); + obj.material = undefined; + } + obj = undefined; + } + + JSROOT.Painter.HPainter_Create3DScene = function(arg) { + + if ((arg!==undefined) && (arg<0)) { + + if (typeof this.TestAxisVisibility === 'function') + this.TestAxisVisibility(null, this.toplevel); + + this.clear_3d_canvas(); + + JSROOT.Painter.DisposeThreejsObject(this.scene); + if (this.control) this.control.dispose(); + + delete this.size3d; + delete this.scene; + delete this.toplevel; + delete this.tooltip_mesh; + delete this.camera; + delete this.pointLight; + delete this.renderer; + delete this.control; + if ('render_tmout' in this) { + clearTimeout(this.render_tmout); + delete this.render_tmout; + } + return; + } + + if ('toplevel' in this) { + // it is indication that all 3D object created, just replace it with empty + + this.scene.remove(this.toplevel); + JSROOT.Painter.DisposeThreejsObject(this.toplevel); + delete this.toplevel; + delete this.tooltip_mesh; + if (this.control) this.control.HideTooltip(); + + var newtop = new THREE.Object3D(); + this.scene.add(newtop); + this.toplevel = newtop; + + return; + } + + var size = this.size_for_3d(); + + this.size3d = 100; + + // three.js 3D drawing + this.scene = new THREE.Scene(); + //scene.fog = new THREE.Fog(0xffffff, 500, 3000); + + this.toplevel = new THREE.Object3D(); + this.scene.add(this.toplevel); + this.scene_width = size.width; + this.scene_height = size.height + + this.camera = new THREE.PerspectiveCamera(45, this.scene_width / this.scene_height, 1, 40*this.size3d); + this.camera.position.set(-1.6*this.size3d, -3.5*this.size3d, 1.4*this.size3d); + + this.pointLight = new THREE.PointLight(0xffffff,1); + this.camera.add( this.pointLight ); + this.pointLight.position.set( this.size3d/2, this.size3d/2, this.size3d/2 ); + + var lookat = new THREE.Vector3(0,0,0.8*this.size3d); + + this.camera.up = new THREE.Vector3(0,0,1); + this.camera.lookAt(lookat); + this.scene.add( this.camera ); + + this.webgl = JSROOT.Painter.TestWebGL(); + + this.renderer = this.webgl ? new THREE.WebGLRenderer({ antialias : true, alpha: true }) : + new THREE.CanvasRenderer({ antialias : true, alpha: true }); + //renderer.setClearColor(0xffffff, 1); + // renderer.setClearColor(0x0, 0); + this.renderer.setSize(this.scene_width, this.scene_height); + + this.add_3d_canvas(size, this.renderer.domElement); + + this.DrawXYZ = JSROOT.Painter.HPainter_DrawXYZ; + this.Render3D = JSROOT.Painter.Render3D; + this.Resize3D = JSROOT.Painter.Resize3D; + this.BinHighlight3D = JSROOT.Painter.BinHighlight3D; + + this.first_render_tm = 0; + this.enable_hightlight = false; + this.enable_tooltip = true; + + this.control = JSROOT.Painter.CreateOrbitControl(this, this.camera, this.scene, this.renderer, lookat); + + var painter = this; + + this.control.ProcessMouseMove = function(intersects) { + var tip = null; + + for (var i = 0; i < intersects.length; ++i) { + if (intersects[i].object.tooltip) { + tip = intersects[i].object.tooltip(intersects[i]); + if (tip) break; + } + } + + if (tip !== null) { + var delta = 1e-4*painter.size3d; + if ((tip.x1 > tip.x2) || (tip.y1 > tip.y2) || (tip.z1 > tip.z2)) console.warn('check 3D hints coordinates'); + tip.x1 -= delta; tip.x2 += delta; + tip.y1 -= delta; tip.y2 += delta; + tip.z1 -= delta; tip.z2 += delta; + } + + painter.BinHighlight3D(tip); + + return (painter.enable_tooltip && tip && tip.info) ? tip.info : ""; + } + + this.control.ProcessMouseLeave = function() { + painter.BinHighlight3D(null); + } + + this.control.ContextMenu = this.ShowContextMenu.bind(this, "hist"); + + } + + JSROOT.Painter.HPainter_TestAxisVisibility = function(camera, toplevel, fb, bb) { + var top; + for (var n=0;n= 0)) qudrant = 2; + if ((pos.x >= 0) && (pos.y >= 0)) qudrant = 3; + if ((pos.x >= 0) && (pos.y < 0)) qudrant = 4; + + function testvisible(id, range) { + if (id <= qudrant) id+=4; + return (id > qudrant) && (id < qudrant+range); + } + + for (var n=0;n 0)) + for (var i=0;i0) break; + } + if (xmin <= 0) xmin = 1e-4*xmax; + this.tx = d3.scale.log(); + this.x_kind = "log"; + } else { + this.tx = d3.scale.linear(); + if (histo && histo.fXaxis.fLabels) this.x_kind = "labels"; + else this.x_kind = "lin"; + } + + this.tx.domain([ xmin, xmax ]).range([ grminx, grmaxx ]); + this.x_handle = new JSROOT.TAxisPainter(histo ? histo.fXaxis : null); + this.x_handle.SetAxisConfig("xaxis", this.x_kind, this.tx, this.xmin, this.xmax, xmin, xmax); + this.x_handle.CreateFormatFuncs(); + + if (pad && pad.fLogy && !use_y_for_z) { + if (ymax <= 0) ymax = 1.; + if ((ymin <= 0) && (this.nbinsy>0)) + for (var i=0;i0) break; + } + + if (ymin <= 0) ymin = 1e-4*ymax; + this.ty = d3.scale.log(); + this.y_kind = "log"; + } else { + this.ty = d3.scale.linear(); + if (histo && histo.fYaxis.fLabels) this.y_kind = "labels"; + else this.y_kind = "lin"; + } + this.ty.domain([ ymin, ymax ]).range([ grminy, grmaxy ]); + this.y_handle = new JSROOT.TAxisPainter(histo ? histo.fYaxis : null); + this.y_handle.SetAxisConfig("yaxis", this.y_kind, this.ty, this.ymin, this.ymax, ymin, ymax); + this.y_handle.CreateFormatFuncs(); + + if (pad && pad.fLogz) { + if (zmax <= 0) zmax = 1; + if (zmin <= 0) zmin = 1e-4*zmax; + this.tz = d3.scale.log(); + this.z_kind = "log"; + } else { + this.tz = d3.scale.linear(); + this.z_kind = "lin"; + } + this.tz.domain([ zmin, zmax ]).range([ grminz, grmaxz ]); + + this.z_handle = new JSROOT.TAxisPainter(histo ? histo.fZaxis : null); + this.z_handle.SetAxisConfig("zaxis", this.z_kind, this.tz, this.zmin, this.zmax, zmin, zmax); + this.z_handle.CreateFormatFuncs(); + + var textMaterial = new THREE.MeshBasicMaterial({ color: 0x000000 }), + lineMaterial = new THREE.LineBasicMaterial({ color: 0x000000 }), + ticklen = textsize*0.5, text, tick, lbls = [], text_scale = 1, + xticks = this.x_handle.CreateTicks(), + yticks = this.y_handle.CreateTicks(), + zticks = this.z_handle.CreateTicks(); + + + // main element, where all axis elements are placed + var top = new THREE.Object3D(); + top.axis_draw = true; // mark element as axis drawing + toplevel.add(top); + + var ticks = [], maxtextheight = 0; + + while (xticks.next()) { + var grx = xticks.grpos; + var is_major = (xticks.kind===1); + var lbl = this.x_handle.format(xticks.tick, true, true); + if (xticks.last_major()) lbl = "x"; else + if (lbl === null) { is_major = false; lbl = ""; } + + if (is_major && lbl && (lbl.length>0)) { + var text3d = new THREE.TextGeometry(lbl, { font: JSROOT.threejs_font_helvetiker_regular, size: textsize, height: 0, curveSegments: 10 }); + text3d.computeBoundingBox(); + var draw_width = text3d.boundingBox.max.x - text3d.boundingBox.min.x, + draw_height = text3d.boundingBox.max.y - text3d.boundingBox.min.y; + text3d.translate(-draw_width/2, 0, 0); + + maxtextheight = Math.max(maxtextheight, draw_height); + + text3d.grx = grx; + lbls.push(text3d); + + if (!xticks.last_major()) { + var space = (xticks.next_major_grpos() - grx); + if (draw_width > 0) + text_scale = Math.min(text_scale, 0.9*space/draw_width) + if (this.x_handle.IsCenterLabels()) text3d.grx += space/2; + } + } + + ticks.push(grx, 0, 0, grx, (is_major ? -ticklen : -ticklen * 0.6), 0); + } + + var ggg1 = new THREE.Geometry(), ggg2 = new THREE.Geometry(); + + lbls.forEach(function(lbl) { + var m = new THREE.Matrix4(); + // matrix to swap y and z scales and shift along z to its position + m.set(text_scale, 0, 0, lbl.grx, + 0, text_scale, 0, -maxtextheight*text_scale - 1.5*ticklen, + 0, 0, 1, 0); + + ggg1.merge(lbl, m); + + m.set(-text_scale, 0, 0, lbl.grx, + 0, text_scale, 0, -maxtextheight*text_scale - 1.5*ticklen, + 0, 0, 1, 0); + + ggg2.merge(lbl, m); + }); + + ggg1 = new THREE.BufferGeometry().fromGeometry(ggg1); + ggg2 = new THREE.BufferGeometry().fromGeometry(ggg2); + + var ticksgeom = new THREE.BufferGeometry(); + ticksgeom.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array(ticks), 3 ) ); + + var xcont = new THREE.Object3D(); + xcont.position.set(0, grminy, grminz) + xcont.rotation.x = 1/4*Math.PI; + xcont.xyid = 2; + xcont.add(new THREE.LineSegments(ticksgeom, lineMaterial)); + xcont.add(new THREE.Mesh(ggg1, textMaterial)); + top.add(xcont); + + xcont = new THREE.Object3D(); + xcont.position.set(0, grmaxy, grminz); + xcont.rotation.x = 3/4*Math.PI; + xcont.add(new THREE.LineSegments(ticksgeom, lineMaterial)); + xcont.add(new THREE.Mesh(ggg2, textMaterial)); + xcont.xyid = 4; + top.add(xcont); + + + lbls = []; text_scale = 1; maxtextheight = 0; ticks = []; + + while (yticks.next()) { + var gry = yticks.grpos; + var is_major = (yticks.kind===1); + var lbl = this.y_handle.format(yticks.tick, true, true); + if (yticks.last_major()) lbl = "y"; else + if (lbl === null) { is_major = false; lbl = ""; } + + if (is_major) { + var text3d = new THREE.TextGeometry(lbl, { font: JSROOT.threejs_font_helvetiker_regular, size: textsize, height: 0, curveSegments: 10 }); + text3d.computeBoundingBox(); + var draw_width = text3d.boundingBox.max.x - text3d.boundingBox.min.x, + draw_height = text3d.boundingBox.max.y - text3d.boundingBox.min.y; + text3d.translate(-draw_width/2, 0, 0); + + maxtextheight = Math.max(maxtextheight, draw_height); + + text3d.gry = gry; + lbls.push(text3d); + + if (!yticks.last_major()) { + var space = (yticks.next_major_grpos() - gry); + if (draw_width > 0) + text_scale = Math.min(text_scale, 0.9*space/draw_width) + if (this.y_handle.IsCenterLabels()) text3d.gry += space/2; + } + } + ticks.push(0,gry,0, (is_major ? -ticklen : -ticklen*0.6), gry, 0); + } + + + var ggg1 = new THREE.Geometry(), ggg2 = new THREE.Geometry(); + + lbls.forEach(function(lbl) { + var m = new THREE.Matrix4(); + m.set(0, text_scale, 0, -maxtextheight*text_scale - 1.5*ticklen, + -text_scale, 0, 0, lbl.gry, + 0, 0, 1, 0); + + ggg1.merge(lbl, m); + + m.set(0, text_scale, 0, -maxtextheight*text_scale - 1.5*ticklen, + text_scale, 0, 0, lbl.gry, + 0, 0, 1, 0); + + ggg2.merge(lbl, m); + + }); + + ggg1 = new THREE.BufferGeometry().fromGeometry(ggg1); + ggg2 = new THREE.BufferGeometry().fromGeometry(ggg2); + + var ticksgeom = new THREE.BufferGeometry(); + ticksgeom.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array(ticks), 3 ) ); + + if (!use_y_for_z) { + var ycont = new THREE.Object3D(); + ycont.position.set(grminx, 0, grminz); + ycont.rotation.y = -1/4*Math.PI; + ycont.add(new THREE.LineSegments(ticksgeom, lineMaterial)); + ycont.add(new THREE.Mesh(ggg1, textMaterial)); + ycont.xyid = 3; + top.add(ycont); + + ycont = new THREE.Object3D(); + ycont.position.set(grmaxx, 0, grminz); + ycont.rotation.y = -3/4*Math.PI; + ycont.add(new THREE.LineSegments(ticksgeom, lineMaterial)); + ycont.add(new THREE.Mesh(ggg2, textMaterial)); + ycont.xyid = 1; + top.add(ycont); + } + + + lbls = []; text_scale = 1; + + var ticks = []; // just array, will be used for the buffer geometry + + var zgridx = null, zgridy = null, lastmajorz = null; + if (this.size3d !== 0) { + zgridx = []; zgridy = []; + } + + while (zticks.next()) { + var grz = zticks.grpos; + var is_major = zticks.kind == 1; + + var lbl = this.z_handle.format(zticks.tick, true, true); + if (lbl === null) { is_major = false; lbl = ""; } + + if (is_major && lbl && (lbl.length > 0)) { + var text3d = new THREE.TextGeometry(lbl, { font: JSROOT.threejs_font_helvetiker_regular, size : textsize, height : 0, curveSegments : 10 }); + text3d.computeBoundingBox(); + var draw_width = text3d.boundingBox.max.x - text3d.boundingBox.min.x, + draw_height = text3d.boundingBox.max.y - text3d.boundingBox.min.y; + text3d.translate(-draw_width, -draw_height/2, 0); + text3d.grz = grz; + lbls.push(text3d); + + if ((lastmajorz !== null) && (draw_height>0)) + text_scale = Math.min(text_scale, 0.9*(grz - lastmajorz)/draw_height); + + lastmajorz = grz; + } + + // create grid + if (zgridx && is_major) + zgridx.push(grminx, 0, grz, grmaxx, 0, grz); + + if (zgridy && is_major) + zgridy.push(0, grminy, grz, 0, grmaxy, grz); + + ticks.push(0, 0, grz, (is_major ? ticklen : ticklen * 0.6), 0, grz); + } + + + if (zgridx && (zgridx.length > 0)) { + + // var material = new THREE.LineBasicMaterial({ color: 0x0, linewidth: 0.5 }); + var material = new THREE.LineDashedMaterial( { color: 0x0, dashSize: 10, gapSize: 2 } ); + + var geom = new THREE.BufferGeometry(); + geom.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array(zgridx), 3 ) ); + + var lines = new THREE.LineSegments(geom, material); + lines.position.set(0,grmaxy,0); + lines.grid = 2; // mark as grid + lines.visible = false; + top.add(lines); + + lines = new THREE.LineSegments(geom, material); + lines.position.set(0,grminy,0); + lines.grid = 4; // mark as grid + lines.visible = false; + top.add(lines); + } + + if (zgridy && (zgridy.length > 0)) { + + // var material = new THREE.LineBasicMaterial({ color: 0x0, linewidth: 0.5 }); + var material = new THREE.LineDashedMaterial( { color: 0x0, dashSize: 10, gapSize: 2 } ); + + var geom = new THREE.BufferGeometry(); + geom.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array(zgridy), 3 ) ); + + var lines = new THREE.LineSegments(geom, material); + lines.position.set(grmaxx,0, 0); + lines.grid = 3; // mark as grid + lines.visible = false; + top.add(lines); + + lines = new THREE.LineSegments(geom, material); + lines.position.set(grminx, 0, 0); + lines.grid = 1; // mark as grid + lines.visible = false; + top.add(lines); + } + + + var ggg = new THREE.Geometry(); + + lbls.forEach(function(lbl) { + var m = new THREE.Matrix4(); + // matrix to swap y and z scales and shift along z to its position + m.set(-text_scale, 0, 0, 2*ticklen, + 0, 0, 1, 0, + 0, text_scale, 0, lbl.grz); + + ggg.merge(lbl, m); + }); + + ggg = new THREE.BufferGeometry().fromGeometry(ggg); + + var ticksgeom = new THREE.BufferGeometry(); + ticksgeom.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array(ticks), 3 ) ); + + // ticks = new THREE.BufferGeometry().fromGeometry(ticks); + + var zcont = []; + for (var n=0;n<4;++n) { + zcont.push(new THREE.Object3D()); + zcont[n].add(new THREE.Mesh(ggg, textMaterial)); + zcont[n].add(new THREE.LineSegments(ticksgeom, lineMaterial)); + zcont[n].zid = n + 2; + top.add(zcont[n]); + } + + zcont[0].position.set(grminx,grmaxy,0); + zcont[0].rotation.z = 3/4*Math.PI; + + zcont[1].position.set(grmaxx,grmaxy,0); + zcont[1].rotation.z = 1/4*Math.PI; + + zcont[2].position.set(grmaxx,grminy,0); + zcont[2].rotation.z = -1/4*Math.PI; + + zcont[3].position.set(grminx,grminy,0); + zcont[3].rotation.z = -3/4*Math.PI; + + + // for TAxis3D do not show final cube + if (this.size3d === 0) return; + + var linex = new THREE.BufferGeometry(); + linex.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array([grminx, 0, 0, grmaxx, 0, 0]), 3 ) ); + for(var n=0;n<2;++n) { + var line = new THREE.LineSegments(linex, lineMaterial); + line.position.set(0, grminy, (n===0) ? grminz : grmaxz); + line.xyboxid = 2; line.bottom = (n == 0); + top.add(line); + + line = new THREE.LineSegments(linex, lineMaterial); + line.position.set(0, grmaxy, (n===0) ? grminz : grmaxz); + line.xyboxid = 4; line.bottom = (n == 0); + top.add(line); + } + + var liney = new THREE.BufferGeometry(); + liney.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array([0, grminy,0, 0, grmaxy, 0]), 3 ) ); + for(var n=0;n<2;++n) { + var line = new THREE.LineSegments(liney, lineMaterial); + line.position.set(grminx, 0, (n===0) ? grminz : grmaxz); + line.xyboxid = 3; line.bottom = (n == 0); + top.add(line); + + line = new THREE.LineSegments(liney, lineMaterial); + line.position.set(grmaxx, 0, (n===0) ? grminz : grmaxz); + line.xyboxid = 1; line.bottom = (n == 0); + top.add(line); + } + + var linez = new THREE.BufferGeometry(); + linez.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array([0, 0, grminz, 0, 0, grmaxz]), 3 ) ); + for(var n=0;n<4;++n) { + var line = new THREE.LineSegments(linez, lineMaterial); + line.zboxid = zcont[n].zid; + line.position.copy(zcont[n].position); + top.add(line); + } + } + + JSROOT.Painter.Box_Vertices = [ + new THREE.Vector3(1, 1, 1), new THREE.Vector3(1, 1, 0), + new THREE.Vector3(1, 0, 1), new THREE.Vector3(1, 0, 0), + new THREE.Vector3(0, 1, 0), new THREE.Vector3(0, 1, 1), + new THREE.Vector3(0, 0, 0), new THREE.Vector3(0, 0, 1) + ]; + + JSROOT.Painter.Box_Indexes = [ 0,2,1, 2,3,1, 4,6,5, 6,7,5, 4,5,1, 5,0,1, 7,6,2, 6,3,2, 5,7,0, 7,2,0, 1,3,4, 3,6,4 ]; + + JSROOT.Painter.Box_Normals = [ 1,0,0, -1,0,0, 0,1,0, 0,-1,0, 0,0,1, 0,0,-1 ]; + + // segments addresses Box_Vertices + JSROOT.Painter.Box_Segments = [0, 2, 2, 7, 7, 5, 5, 0, 1, 3, 3, 6, 6, 4, 4, 1, 1, 0, 3, 2, 6, 7, 4, 5]; + + // these segments address vertices from the mesh, we can use positions from box mesh + JSROOT.Painter.Box_MeshSegments = (function() { + var arr = new Int32Array(JSROOT.Painter.Box_Segments.length); + for (var n=0;n0), hdim = this.Dimension(); + + var i1 = this.GetSelectIndex("x", "left", 0), + i2 = this.GetSelectIndex("x", "right", 1), + j1 = (hdim===1) ? 0 : this.GetSelectIndex("y", "left", 0), + j2 = (hdim===1) ? 1 : this.GetSelectIndex("y", "right", 1), + i, j, x1, x2, y1, y2, binz, reduced, nobottom, notop, + main = this.main_painter(), + split_faces = (this.options.Lego === 11) || (this.options.Lego === 13); // split each layer on two parts + + var xx = new Float32Array(i2+1), + yy = new Float32Array(j2+1); + + // first adjust ranges + for (i=i1;i<=i2;++i) { + x1 = this.GetBinX(i); + if (main.logx && (x1 <= 0)) { i1 = i+1; continue; } + xx[i] = this.tx(x1); + + if (xx[i] < -1.001*this.size3d) i1 = i+1; + if (xx[i] > 1.001*this.size3d) i2 = i-1; + } + + if (hdim===1) { + yy[0] = this.ty(0); + yy[1] = this.ty(1); + } else { + for (j=j1;j<=j2;++j) { + y1 = this.GetBinY(j); + if (main.logy && (y1 <= 0)) { j1 = j+1; continue; } + yy[j] = this.ty(y1); + if (yy[j] < -1.001*this.size3d) j1 = j+1; + if (yy[j] > 1.001*this.size3d) j2 = j-1; + } + } + + if ((i1 >= i2) || (j1>=j2)) return; + + // if bin ID fit into 16 bit, use smaller arrays for intersect indexes + var use16indx = (this.histo.getBin(i2, j2) < 0xFFFF); + + // DRAW ALL CUBES + + var levels = [ axis_zmin, axis_zmax ], palette = null, totalvertices = 0; + + if ((this.options.Lego === 12) || (this.options.Lego === 14)) { + var nlevels = 20; + if (this.histo.fContour != null) nlevels = this.histo.fContour.length; + levels = this.CreateContour(nlevels, this.lego_zmin, this.lego_zmax); + palette = this.GetPalette(); + } + + for (var nlevel=0; nlevel0) || !showmin)) continue; + nobottom = !reduced && (nlevel>0); + notop = !reduced && (binz > zmax) && (nlevel < levels.length-2); + + numvertices += (reduced ? 12 : indicies.length); + if (nobottom) numvertices -= 6; + if (notop) numvertices -= 6; + + if (split_faces && !reduced) { + numvertices -= 12; + num2vertices += 12; + } + } + + totalvertices += numvertices + num2vertices; + + var positions = new Float32Array(numvertices*3), + normals = new Float32Array(numvertices*3), + bins_index = use16indx ? new Uint16Array(numvertices) : new Uint32Array(numvertices), + pos2 = null, norm2 = null, indx2 = null, + v = 0, v2 = 0, vert, bin, k, nn; + + if (num2vertices > 0) { + pos2 = new Float32Array(num2vertices*3); + norm2 = new Float32Array(num2vertices*3); + indx2 = use16indx ? new Uint16Array(num2vertices) : new Uint32Array(num2vertices); + } + + for (i=i1;i0) || !showmin)) continue; + nobottom = !reduced && (nlevel>0); + notop = !reduced && (binz > zmax) && (nlevel < levels.length-2); + + y1 = yy[j]; + y2 = yy[j+1]; + + z2 = (binz > zmax) ? zzz : this.tz(binz); + + nn = 0; // counter over the normals, each normals correspond to 6 vertices + k = 0; // counter over vertices + + if (reduced) { + // we skip all side faces, keep only top and bottom + nn += 12; + k += 24; + } + + var size = indicies.length, bin_index = this.histo.getBin(i+1, j+1); + if (nobottom) size -= 6; + + // array over all vertices of the single bin + while(k < size) { + + vert = vertices[indicies[k]]; + + if (split_faces && (k < 12)) { + pos2[v2] = x1 + vert.x * (x2 - x1); + pos2[v2+1] = y1 + vert.y * (y2 - y1); + pos2[v2+2] = z1 + vert.z * (z2 - z1); + + norm2[v2] = vnormals[nn]; + norm2[v2+1] = vnormals[nn+1]; + norm2[v2+2] = vnormals[nn+2]; + + indx2[v2/3] = bin_index; // remember which bin corresponds to the vertex + v2+=3; + } else { + positions[v] = x1 + vert.x * (x2 - x1); + positions[v+1] = y1 + vert.y * (y2 - y1); + positions[v+2] = z1 + vert.z * (z2 - z1); + + normals[v] = vnormals[nn]; + normals[v+1] = vnormals[nn+1]; + normals[v+2] = vnormals[nn+2]; + bins_index[v/3] = bin_index; // remember which bin corresponds to the vertex + v+=3; + } + + ++k; + + if (k%6 === 0) { + nn+=3; + if (notop && (k === indicies.length - 12)) { + k+=6; nn+=3; // jump over notop indexes + } + } + } + } + } + + var geometry = new THREE.BufferGeometry(); + geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) ); + geometry.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) ); + // geometry.computeVertexNormals(); + + var rootcolor = this.GetObject().fFillColor, + fcolor = JSROOT.Painter.root_colors[rootcolor]; + + if (palette) { + var indx = Math.floor((nlevel+0.99)*palette.length/(levels.length-1)); + if (indx > palette.length-1) indx = palette.length-1; + fcolor = palette[indx]; + } + + //var material = new THREE.MeshLambertMaterial( { color: fcolor } ); + var material = new THREE.MeshBasicMaterial( { color: fcolor, shading: THREE.SmoothShading } ); + + var mesh = new THREE.Mesh(geometry, material); + + mesh.bins_index = bins_index; + mesh.painter = this; + mesh.zmin = axis_zmin; + mesh.zmax = axis_zmax; + mesh.tip_color = (rootcolor===3) ? 0xFF0000 : 0x00FF00; + + mesh.tooltip = function(intersect) { + if ((intersect.index<0) || (intersect.index >= this.bins_index.length)) return null; + var p = this.painter, + tip = p.Get3DToolTip( this.bins_index[intersect.index] ); + + tip.x1 = p.tx(p.GetBinX(tip.ix-1)); + tip.x2 = p.tx(p.GetBinX(tip.ix)); + if (p.Dimension()===1) { + tip.y1 = p.ty(0); + tip.y2 = p.ty(1); + } else { + tip.y1 = p.ty(p.GetBinY(tip.iy-1)); + tip.y2 = p.ty(p.GetBinY(tip.iy)); + } + tip.z1 = p.tz(this.zmin); + tip.z2 = p.tz(this.zmax); + + if (tip.value 0) { + var geom2 = new THREE.BufferGeometry(); + geom2.addAttribute( 'position', new THREE.BufferAttribute( pos2, 3 ) ); + geom2.addAttribute( 'normal', new THREE.BufferAttribute( norm2, 3 ) ); + //geom2.computeVertexNormals(); + + //var material2 = new THREE.MeshLambertMaterial( { color: 0xFF0000 } ); + var material2 = new THREE.MeshBasicMaterial( { color: 0xFF0000, shading: THREE.SmoothShading } ); + + var mesh2 = new THREE.Mesh(geom2, material2); + mesh2.bins_index = indx2; + mesh2.painter = this; + mesh2.tooltip = mesh.tooltip; + mesh2.zmin = mesh.zmin; + mesh2.zmax = mesh.zmax; + mesh2.tip_color = mesh.tip_color; + + this.toplevel.add(mesh2); + } + } + + // console.log('Total number of lego vertices', totalvertices); + + // lego3 or lego4 do not draw border lines + if (this.options.Lego > 12) return; + + // DRAW LINE BOXES + + var numlinevertices = 0, numsegments = 0, uselineindx = true; + + for (i=i1;i 0xFFF0) uselineindx = false; + + if (!uselineindx) numlinevertices = numsegments*3; + + var lpositions = new Float32Array( numlinevertices * 3 ), + lindicies = uselineindx ? new Uint16Array( numsegments ) : null; +// intersect_size = uselineindx ? numsegments : numlinevertices, +// intersect_index = use16indx ? new Uint16Array( intersect_size ) : new Uint32Array( intersect_size ); + + var z1 = this.tz(axis_zmin), zzz = this.tz(axis_zmax), + z2 = 0, ll = 0, ii = 0; + + for (i=i1;i zmax) ? zzz : this.tz(binz); + + var seg = reduced ? rsegments : segments, + vvv = reduced ? rvertices : vertices; +// bin_index = this.histo.getBin(i+1, j+1); + + + if (uselineindx) { + // array of indicies for the lines, to avoid duplication of points + for (k=0; k < seg.length; ++k) { +// intersect_index[ii] = bin_index; + lindicies[ii++] = ll/3 + seg[k]; + } + + for (k=0; k < vvv.length; ++k) { + vert = vvv[k]; + lpositions[ll] = x1 + vert.x * (x2 - x1); + lpositions[ll+1] = y1 + vert.y * (y2 - y1); + lpositions[ll+2] = z1 + vert.z * (z2 - z1); + ll+=3; + } + } else { + // copy only vertex positions + for (k=0; k < seg.length; ++k) { + vert = vvv[seg[k]]; + lpositions[ll] = x1 + vert.x * (x2 - x1); + lpositions[ll+1] = y1 + vert.y * (y2 - y1); + lpositions[ll+2] = z1 + vert.z * (z2 - z1); +// intersect_index[ll/3] = bin_index; + ll+=3; + } + } + } + } + + // create boxes + geometry = new THREE.BufferGeometry(); + geometry.addAttribute( 'position', new THREE.BufferAttribute( lpositions, 3 ) ); + if (uselineindx) + geometry.setIndex(new THREE.BufferAttribute(lindicies, 1)); + + var lcolor = JSROOT.Painter.root_colors[this.GetObject().fLineColor]; + + material = new THREE.LineBasicMaterial({ color: new THREE.Color(lcolor) }); + if (!JSROOT.browser.isIE) material.linewidth = this.GetObject().fLineWidth; + var line = new THREE.LineSegments(geometry, material); + + /* + line.painter = this; + line.intersect_index = intersect_index; + line.tooltip = function(intersect) { + if ((intersect.index<0) || (intersect.index >= this.intersect_index.length)) return null; + return this.painter.Get3DToolTip(this.intersect_index[intersect.index]); + } + */ + + this.toplevel.add(line); + } + + JSROOT.Painter.Render3D = function(tmout) { + if (tmout === undefined) tmout = 5; // by default, rendering happens with timeout + + if (tmout <= 0) { + if ('render_tmout' in this) + clearTimeout(this.render_tmout); + + if (this.renderer === undefined) return; + + var tm1 = new Date(); + + if (typeof this.TestAxisVisibility === 'function') + this.TestAxisVisibility(this.camera, this.toplevel, this.options.FrontBox, this.options.BackBox); + + // do rendering, most consuming time + this.renderer.render(this.scene, this.camera); + + var tm2 = new Date(); + + delete this.render_tmout; + + if (this.first_render_tm === 0) { + this.first_render_tm = tm2.getTime() - tm1.getTime(); + this.enable_hightlight = this.first_render_tm < 1200; + console.log('First render tm = ' + this.first_render_tm); + } + + return; + } + + // no need to shoot rendering once again + if ('render_tmout' in this) return; + + this.render_tmout = setTimeout(this.Render3D.bind(this,0), tmout); + } + + JSROOT.Painter.Resize3D = function() { + + var size3d = this.size_for_3d(this.access_3d_kind()); + + this.apply_3d_size(size3d); + + if ((this.scene_width === size3d.width) && (this.scene_height === size3d.height)) return; + + if ((size3d.width<10) || (size3d.height<10)) return; + + this.scene_width = size3d.width; + this.scene_height = size3d.height; + + this.camera.aspect = this.scene_width / this.scene_height; + this.camera.updateProjectionMatrix(); + + this.renderer.setSize( this.scene_width, this.scene_height ); + + this.Render3D(); + } + + JSROOT.Painter.TH1Painter_Draw3D = function(call_back, resize) { + // function called with this as painter + + if (resize) { + + this.Resize3D(); + + } else { + + this.Create3DScene(); + this.Draw3DBins = JSROOT.Painter.HistPainter_DrawLego; + + this.DeleteAtt(); + + this.DrawXYZ(this.toplevel, true, 1.1); + + this.Draw3DBins(); + + this.Render3D(); + } + + // (re)draw palette by resize while canvas may change dimension + this.DrawColorPalette((this.options.Zscale > 0) && ((this.options.Lego===12) || (this.options.Lego===14))); + + this.DrawTitle(); + + JSROOT.CallBack(call_back); + } + + + JSROOT.Painter.TH2Painter_Draw3D = function(call_back, resize) { + // function called with this as painter + + if (resize) { + + this.Resize3D(); + + } else { + + this.Create3DScene(); + this.Draw3DBins = JSROOT.Painter.HistPainter_DrawLego; + + var pad = this.root_pad(); + // if (pad && pad.fGridz === undefined) pad.fGridz = false; + + this.zmin = pad.fLogz ? this.gmin0bin * 0.3 : this.gminbin; + this.zmax = this.gmaxbin; + + if (this.histo.fMinimum !== -1111) this.zmin = this.histo.fMinimum; + if (this.histo.fMaximum !== -1111) this.zmax = this.histo.fMaximum; + + if (pad.fLogz && (this.zmin<=0)) this.zmin = this.zmax * 1e-5; + + this.DeleteAtt(); + + this.DrawXYZ(this.toplevel, false, 1.1); + + this.Draw3DBins(); + + this.Render3D(); + } + + // (re)draw palette by resize while canvas may change dimension + this.DrawColorPalette((this.options.Zscale > 0) && ((this.options.Lego===12) || (this.options.Lego===14))); + + this.DrawTitle(); + + JSROOT.CallBack(call_back); + } + + // ============================================================================== + + + JSROOT.TH3Painter = function(histo) { + JSROOT.THistPainter.call(this, histo); + + this.Create3DScene = JSROOT.Painter.HPainter_Create3DScene; + } + + JSROOT.TH3Painter.prototype = Object.create(JSROOT.THistPainter.prototype); + + JSROOT.TH3Painter.prototype.ScanContent = function() { + var histo = this.GetObject(); + + this.nbinsx = histo.fXaxis.fNbins; + this.nbinsy = histo.fYaxis.fNbins; + this.nbinsz = histo.fZaxis.fNbins; + + this.xmin = histo.fXaxis.fXmin; + this.xmax = histo.fXaxis.fXmax; + + this.ymin = histo.fYaxis.fXmin; + this.ymax = histo.fYaxis.fXmax; + + this.zmin = histo.fZaxis.fXmin; + this.zmax = histo.fZaxis.fXmax; + + // global min/max, used at the moment in 3D drawing + + this.gminbin = this.gmaxbin = histo.getBinContent(1,1,1); + var i,j,k; + for (i = 0; i < this.nbinsx; ++i) + for (j = 0; j < this.nbinsy; ++j) + for (k = 0; k < this.nbinsz; ++k) { + var bin_content = histo.getBinContent(i+1, j+1, k+1); + if (bin_content < this.gminbin) this.gminbin = bin_content; else + if (bin_content > this.gmaxbin) this.gmaxbin = bin_content; + } + + this.draw_content = this.gmaxbin > 0; + + this.CreateAxisFuncs(true, true); + } + + JSROOT.TH3Painter.prototype.CountStat = function() { + var histo = this.GetObject(), + stat_sum0 = 0, stat_sumx1 = 0, stat_sumy1 = 0, + stat_sumz1 = 0, stat_sumx2 = 0, stat_sumy2 = 0, stat_sumz2 = 0, + i1 = this.GetSelectIndex("x", "left"), + i2 = this.GetSelectIndex("x", "right"), + j1 = this.GetSelectIndex("y", "left"), + j2 = this.GetSelectIndex("y", "right"), + k1 = this.GetSelectIndex("z", "left"), + k2 = this.GetSelectIndex("z", "right"), + res = { entries: 0, integral: 0, meanx: 0, meany: 0, meanz: 0, rmsx: 0, rmsy: 0, rmsz: 0 }; + + for (var xi = 0; xi < this.nbinsx+2; ++xi) { + + var xx = this.GetBinX(xi - 0.5); + var xside = (xi < i1) ? 0 : (xi > i2 ? 2 : 1); + + for (var yi = 0; yi < this.nbinsy+2; ++yi) { + + var yy = this.GetBinY(yi - 0.5); + var yside = (yi < j1) ? 0 : (yi > j2 ? 2 : 1); + + for (var zi = 0; zi < this.nbinsz+2; ++zi) { + + var zz = this.GetBinZ(zi - 0.5); + var zside = (zi < k1) ? 0 : (zi > k2 ? 2 : 1); + + var cont = histo.getBinContent(xi, yi, zi); + res.entries += cont; + + if ((xside==1) && (yside==1) && (zside==1)) { + stat_sum0 += cont; + stat_sumx1 += xx * cont; + stat_sumy1 += yy * cont; + stat_sumz1 += zz * cont; + stat_sumx2 += xx * xx * cont; + stat_sumy2 += yy * yy * cont; + stat_sumz2 += zz * zz * cont; + } + } + } + } + + if (histo.fTsumw > 0) { + stat_sum0 = histo.fTsumw; + stat_sumx1 = histo.fTsumwx; + stat_sumx2 = histo.fTsumwx2; + stat_sumy1 = histo.fTsumwy; + stat_sumy2 = histo.fTsumwy2; + stat_sumz1 = histo.fTsumwz; + stat_sumz2 = histo.fTsumwz2; + } + + if (stat_sum0 > 0) { + res.meanx = stat_sumx1 / stat_sum0; + res.meany = stat_sumy1 / stat_sum0; + res.meanz = stat_sumz1 / stat_sum0; + res.rmsx = Math.sqrt(stat_sumx2 / stat_sum0 - res.meanx * res.meanx); + res.rmsy = Math.sqrt(stat_sumy2 / stat_sum0 - res.meany * res.meany); + res.rmsz = Math.sqrt(stat_sumz2 / stat_sum0 - res.meanz * res.meanz); + } + + res.integral = stat_sum0; + + if (histo.fEntries > 1) res.entries = histo.fEntries; + + return res; + } + + JSROOT.TH3Painter.prototype.FillStatistic = function(stat, dostat, dofit) { + if (this.GetObject()===null) return false; + + var pave = stat.GetObject(), + data = this.CountStat(), + print_name = dostat % 10, + print_entries = Math.floor(dostat / 10) % 10, + print_mean = Math.floor(dostat / 100) % 10, + print_rms = Math.floor(dostat / 1000) % 10, + print_under = Math.floor(dostat / 10000) % 10, + print_over = Math.floor(dostat / 100000) % 10, + print_integral = Math.floor(dostat / 1000000) % 10; + //var print_skew = Math.floor(dostat / 10000000) % 10; + //var print_kurt = Math.floor(dostat / 100000000) % 10; + + if (print_name > 0) + pave.AddText(this.GetObject().fName); + + if (print_entries > 0) + pave.AddText("Entries = " + stat.Format(data.entries,"entries")); + + if (print_mean > 0) { + pave.AddText("Mean x = " + stat.Format(data.meanx)); + pave.AddText("Mean y = " + stat.Format(data.meany)); + pave.AddText("Mean z = " + stat.Format(data.meanz)); + } + + if (print_rms > 0) { + pave.AddText("Std Dev x = " + stat.Format(data.rmsx)); + pave.AddText("Std Dev y = " + stat.Format(data.rmsy)); + pave.AddText("Std Dev z = " + stat.Format(data.rmsz)); + } + + if (print_integral > 0) { + pave.AddText("Integral = " + stat.Format(data.integral,"entries")); + } + + // adjust the size of the stats box with the number of lines + + var nlines = pave.fLines.arr.length, + stath = nlines * JSROOT.gStyle.StatFontSize; + if (stath <= 0 || 3 == (JSROOT.gStyle.StatFont % 10)) { + stath = 0.25 * nlines * JSROOT.gStyle.StatH; + pave.fY1NDC = 0.93 - stath; + pave.fY2NDC = 0.93; + } + + return true; + } + + JSROOT.TH3Painter.prototype.GetBinTips = function (ix, iy, iz) { + var lines = []; + lines.push(this.GetTipName()); + lines.push('x=' + JSROOT.FFormat(this.GetBinX(ix+0.5),"6.4g") + ' bin=' + (ix+1)); + lines.push('y=' + JSROOT.FFormat(this.GetBinY(iy+0.5),"6.4g") + ' bin=' + (iy+1)); + lines.push('z=' + JSROOT.FFormat(this.GetBinZ(iz+0.5),"6.4g") + ' bin=' + (iz+1)); + lines.push('entries=' + JSROOT.FFormat(this.GetObject().getBinContent(ix+1, iy+1, iz+1), "7.0g")); + return lines; + } + + JSROOT.TH3Painter.prototype.Draw3DBins = function() { + + if (!this.draw_content) return; + + var rootcolor = this.GetObject().fFillColor, + fillcolor = JSROOT.Painter.root_colors[rootcolor], + material = null, buffer_size = 0, helper = null, helper_kind = 0, + single_bin_verts, single_bin_norms; + + + if (this.options.Box === 11) { + // material = new THREE.MeshPhongMaterial({ color : fillcolor /*, specular : 0x4f4f4f */ }); + // material = new THREE.MeshBasicMaterial( { color: fillcolor, shading: THREE.SmoothShading } ); + material = new THREE.MeshLambertMaterial({ color : fillcolor }); + + var geom = JSROOT.Painter.TestWebGL() ? new THREE.SphereGeometry(0.5, 16, 12) : new THREE.SphereGeometry(0.5, 8, 6); + geom.applyMatrix( new THREE.Matrix4().makeRotationX( Math.PI / 2 ) ); + + buffer_size = geom.faces.length*9; + single_bin_verts = new Float32Array(buffer_size); + single_bin_norms = new Float32Array(buffer_size); + + // Fill a typed array with cube geometry that will be shared by all + // (This technically could be put into an InstancedBufferGeometry but + // performance gain is likely not huge ) + for (var face = 0; face < geom.faces.length; ++face) { + single_bin_verts[9*face ] = geom.vertices[geom.faces[face].a].x; + single_bin_verts[9*face+1] = geom.vertices[geom.faces[face].a].y; + single_bin_verts[9*face+2] = geom.vertices[geom.faces[face].a].z; + single_bin_verts[9*face+3] = geom.vertices[geom.faces[face].b].x; + single_bin_verts[9*face+4] = geom.vertices[geom.faces[face].b].y; + single_bin_verts[9*face+5] = geom.vertices[geom.faces[face].b].z; + single_bin_verts[9*face+6] = geom.vertices[geom.faces[face].c].x; + single_bin_verts[9*face+7] = geom.vertices[geom.faces[face].c].y; + single_bin_verts[9*face+8] = geom.vertices[geom.faces[face].c].z; + + single_bin_norms[9*face ] = geom.faces[face].vertexNormals[0].x; + single_bin_norms[9*face+1] = geom.faces[face].vertexNormals[0].y; + single_bin_norms[9*face+2] = geom.faces[face].vertexNormals[0].z; + single_bin_norms[9*face+3] = geom.faces[face].vertexNormals[1].x; + single_bin_norms[9*face+4] = geom.faces[face].vertexNormals[1].y; + single_bin_norms[9*face+5] = geom.faces[face].vertexNormals[1].z; + single_bin_norms[9*face+6] = geom.faces[face].vertexNormals[2].x; + single_bin_norms[9*face+7] = geom.faces[face].vertexNormals[2].y; + single_bin_norms[9*face+8] = geom.faces[face].vertexNormals[2].z; + } + + } else { + // material = new THREE.MeshLambertMaterial({ color : fillcolor }); + + material = new THREE.MeshBasicMaterial( { color: fillcolor } ); + + var indicies = JSROOT.Painter.Box_Indexes, + normals = JSROOT.Painter.Box_Normals, + vertices = JSROOT.Painter.Box_Vertices; + + buffer_size = indicies.length*3; + single_bin_verts = new Float32Array(buffer_size); + single_bin_norms = new Float32Array(buffer_size); + + for (var k=0,nn=-3;k"); + + var scalex = (this.tx(this.GetBinX(i2+0.5)) - this.tx(this.GetBinX(i1+0.5))) / (i2-i1), + scaley = (this.ty(this.GetBinY(j2+0.5)) - this.ty(this.GetBinY(j1+0.5))) / (j2-j1), + scalez = (this.tz(this.GetBinZ(k2+0.5)) - this.tz(this.GetBinZ(k1+0.5))) / (k2-k1); + + var nbins = 0, i, j, k, wei, bin_content; + + for (i = i1; i < i2; ++i) { + for (j = j1; j < j2; ++j) { + for (k = k1; k < k2; ++k) { + bin_content = histo.getBinContent(i+1, j+1, k+1); + if (bin_content <= this.gminbin) continue; + wei = (this.options.Color > 0) ? 1. : bin_content / this.gmaxbin; + if (wei < 1e-5) continue; // do not empty or very small bins + + nbins++; + } + } + } + + // console.log("Create buffer for", nbins, 'bins fullsize', nbins * buffer_size); + + if ((helper_kind === 1) && (nbins * buffer_size / 3 > 0xFFF0)) helper_kind = 2; + + var bin_verts = new Float32Array(nbins * buffer_size), + bin_norms = new Float32Array(nbins * buffer_size), + bin_tooltips = new Int32Array(nbins), + helper_segments, + helper_indexes, // helper_kind == 1, use original vertices + helper_positions; // helper_kind == 2, all vertices copied into separate buffer + + if (helper_kind===1) { + helper_segments = JSROOT.Painter.Box_MeshSegments; + helper_indexes = new Uint16Array(nbins * helper_segments.length); + } + + if (helper_kind===2) { + helper_segments = JSROOT.Painter.Box_Segments; + helper_positions = new Float32Array(nbins * helper_segments.length * 3); + } + + var binx, grx, biny, gry, binz, grz; + + nbins = 0; + + for (i = i1; i < i2; ++i) { + binx = this.GetBinX(i+0.5); grx = this.tx(binx); + for (j = j1; j < j2; ++j) { + biny = this.GetBinY(j+0.5); gry = this.ty(biny); + for (k = k1; k < k2; ++k) { + bin_content = histo.getBinContent(i+1, j+1, k+1); + if (bin_content <= this.gminbin) continue; + + wei = /*(this.options.Color > 0) ? 1. :*/ bin_content / this.gmaxbin; + if (wei < 1e-5) continue; // do not show empty bins + + binz = this.GetBinZ(k+0.5); grz = this.tz(binz); + + // remeber bin index for tooltip + bin_tooltips[nbins] = histo.getBin(i+1, j+1, k+1); + + var vvv = nbins * buffer_size; + + // Grab the coordinates and scale that are being assigned to each bin + for (var vi = 0; vi < buffer_size; vi+=3, vvv+=3) { + bin_verts[vvv] = grx + single_bin_verts[vi]*scalex*wei; + bin_verts[vvv+1] = gry + single_bin_verts[vi+1]*scaley*wei; + bin_verts[vvv+2] = grz + single_bin_verts[vi+2]*scalez*wei; + + bin_norms[vvv] = single_bin_norms[vi]; + bin_norms[vvv+1] = single_bin_norms[vi+1]; + bin_norms[vvv+2] = single_bin_norms[vi+2]; + } + + + if (helper_kind===1) { + // reuse vertices created for the mesh + vvv = nbins * helper_segments.length; + var shift = Math.round(nbins * buffer_size/3); + for (var n=0;n= this.bins.length)) return null; + + var p = this.painter, + tip = p.Get3DToolTip(this.bins[indx]); + + grx = p.tx(p.GetBinX(tip.ix-0.5)); + gry = p.ty(p.GetBinY(tip.iy-0.5)); + grz = p.tz(p.GetBinZ(tip.iz-0.5)); + + wei = tip.value / p.gmaxbin; + + tip.x1 = grx - this.scalex*wei; tip.x2 = grx + this.scalex*wei; + tip.y1 = gry - this.scaley*wei; tip.y2 = gry + this.scaley*wei; + tip.z1 = grz - this.scalez*wei; tip.z2 = grz + this.scalez*wei; + + tip.color = this.tip_color; + + return tip; + } + + this.toplevel.add(combined_bins); + + if (helper_kind > 0) { + var helper_geom = new THREE.BufferGeometry(); + + if (helper_kind === 1) { + // reuse positions from the mesh - only special index was created + helper_geom.setIndex( new THREE.BufferAttribute(helper_indexes, 1) ); + helper_geom.addAttribute( 'position', new THREE.BufferAttribute( bin_verts, 3 ) ); + } else { + helper_geom.addAttribute( 'position', new THREE.BufferAttribute( helper_positions, 3 ) ); + } + + var helper_material = new THREE.LineBasicMaterial( { color: 0x000000 } ); + + var lines = new THREE.LineSegments(helper_geom, helper_material ); + + this.toplevel.add(lines); + + //lines.bins = bins; + //lines.bins_faces = helper_single_indexes.length; + //lines.painter = this; + //lines.tooltip = combined_bins.tooltip; + } + } + + JSROOT.TH3Painter.prototype.Redraw = function(resize) { + if (resize) { + this.Resize3D(); + } else { + this.Create3DScene(); + this.DrawXYZ(this.toplevel); + this.Draw3DBins(); + this.Render3D(); + } + } + + JSROOT.TH3Painter.prototype.FillToolbar = function() { + var pp = this.pad_painter(true); + if (pp===null) return; + + pp.AddButton(JSROOT.ToolbarIcons.undo, 'Unzoom all axes', 'UnzoomAllAxis'); + if (this.draw_content) + pp.AddButton(JSROOT.ToolbarIcons.statbox, 'Toggle stat box', "ToggleStatBox"); + } + + JSROOT.TH3Painter.prototype.FillHistContextMenu = function(menu) { + menu.addDrawMenu("Draw with", ["box", "box1"], function(arg) { + this.options = this.DecodeOptions(arg); + this.Redraw(); + }); + } + + JSROOT.Painter.drawHistogram3D = function(divid, histo, opt) { + // when called, *this* set to painter instance + + // create painter and add it to canvas + JSROOT.extend(this, new JSROOT.TH3Painter(histo)); + + this.SetDivId(divid, 4); + + this.options = this.DecodeOptions(opt); + + this.CheckPadRange(); + + this.ScanContent(); + + this.Redraw(); + + this.DrawTitle(); + + if (JSROOT.gStyle.AutoStat && this.create_canvas) { + var stats = this.CreateStat(); + if (stats) JSROOT.draw(this.divid, stats, ""); + } + + this.FillToolbar(); + + return this.DrawingReady(); + } + + // =================================================================== + + JSROOT.Painter.drawPolyMarker3D = function(divid, poly, opt) { + // when called, *this* set to painter instance + + this.SetDivId(divid); + + var main = this.main_painter(); + + if (!main || !('renderer' in main)) return this.DrawingReady(); + + var step = 3, sizelimit = main.webgl ? 50000 : 5000; + + if ((JSROOT.gStyle.OptimizeDraw > 0) && (poly.fP.length > 3 * sizelimit)) { + step = Math.floor(poly.fP.length / sizelimit / 3 ) * 3; + if (step <= 6) step = 6; + } + + var size = Math.floor(poly.fP.length/step), + indicies = JSROOT.Painter.Box_Indexes, + normals = JSROOT.Painter.Box_Normals, + vertices = JSROOT.Painter.Box_Vertices, + pos = new Float32Array(indicies.length*3*size), + norm = new Float32Array(indicies.length*3*size), + lll = 0, scale = main.size3d/100; + + for (var i=0; i < size*step; i+=step) { + var x = main.tx(poly.fP[i]), + y = main.ty(poly.fP[i+1]), + z = main.tz(poly.fP[i+2]); + + for (var k=0,nn=-3;k= this.poly.fP.length)) return null; + var p = this.painter; + + var tip = { info: "bin: " + indx/3 + "
" + + "x: " + p.x_handle.format(this.poly.fP[indx]) + "
" + + "y: " + p.y_handle.format(this.poly.fP[indx+1]) + "
" + + "z: " + p.z_handle.format(this.poly.fP[indx+2]) }; + + var grx = p.tx(this.poly.fP[indx]), + gry = p.ty(this.poly.fP[indx+1]), + grz = p.tz(this.poly.fP[indx+2]); + + tip.x1 = grx - this.scale0; tip.x2 = grx + this.scale0; + tip.y1 = gry - this.scale0; tip.y2 = gry + this.scale0; + tip.z1 = grz - this.scale0; tip.z2 = grz + this.scale0; + + tip.color = this.tip_color; + + return tip; + } + + main.Render3D(100); // set large timeout to be able draw other points + + return this.DrawingReady(); + } + + return JSROOT.Painter; + +})); + diff --git a/visualisations/JsRoot460/scripts/JSRoot3DPainter.min.js b/visualisations/JsRoot460/scripts/JSRoot3DPainter.min.js new file mode 100644 index 0000000..e10171d --- /dev/null +++ b/visualisations/JsRoot460/scripts/JSRoot3DPainter.min.js @@ -0,0 +1 @@ +(function(a){if(typeof define==="function"&&define.amd){define(["d3","JSRootPainter","threejs_all"],a)}else{if(typeof JSROOT=="undefined"){throw new Error("JSROOT is not defined","JSRoot3DPainter.js")}if(typeof d3!="object"){throw new Error("This extension requires d3.v3.js","JSRoot3DPainter.js")}if(typeof JSROOT.Painter!="object"){throw new Error("JSROOT.Painter is not defined","JSRoot3DPainter.js")}if(typeof THREE=="undefined"){throw new Error("THREE is not defined","JSRoot3DPainter.js")}a(d3,JSROOT)}}(function(b,a){a.Painter.TestWebGL=function(){if(a.gStyle.NoWebGL){return false}if("_Detect_WebGL" in this){return this._Detect_WebGL}try{var c=document.createElement("canvas");this._Detect_WebGL=!!(window.WebGLRenderingContext&&(c.getContext("webgl")||c.getContext("experimental-webgl")))}catch(d){return false}return this._Detect_WebGL};a.Painter.TooltipFor3D=function(d,c){this.tt=null;this.cont=null;this.lastlbl="";this.parent=d?d:document.body;this.canvas=c;this.abspos=!d;this.pos=function(n){if(this.tt===null){return}var k,h;if(this.abspos){h=a.browser.isIE?(n.clientX+document.documentElement.scrollLeft):n.pageX;k=a.browser.isIE?(n.clientY+document.documentElement.scrollTop):n.pageY}else{h=n.offsetX;k=n.offsetY;var i=this.parent.getBoundingClientRect(),g=this.canvas.getBoundingClientRect();if((i.left!==undefined)&&(g.left!==undefined)){h+=(g.left-i.left)}if((i.top!==undefined)&&(g.top!==undefined)){k+=g.top-i.top}if(h+this.tt.offsetWidth+3>=this.parent.offsetWidth){h=this.parent.offsetWidth-this.tt.offsetWidth-3}if(k+this.tt.offsetHeight+15>=this.parent.offsetHeight){k=this.parent.offsetHeight-this.tt.offsetHeight-15}var f=this.parent;while(f){var m=getComputedStyle(f);if(!m||(m.position!=="static")){break}if(!f.parentNode||(f.parentNode.nodeType!=1)){break}f=f.parentNode}if(f&&(f!==this.parent)){var j=f.getBoundingClientRect();h+=(i.left-j.left);k+=(i.top-j.top)}}this.tt.style.top=(k+15)+"px";this.tt.style.left=(h+3)+"px"};this.show=function(f){if(a.gStyle.Tooltip<=0){return}if(!f||f===""){return this.hide()}if(this.tt===null){this.tt=document.createElement("div");this.tt.setAttribute("class","jsroot");var g=document.createElement("div");g.setAttribute("class","tt3d_border");this.cont=document.createElement("div");this.cont.setAttribute("class","tt3d_cont");var e=document.createElement("div");e.setAttribute("class","tt3d_border");this.tt.appendChild(g);this.tt.appendChild(this.cont);this.tt.appendChild(e);this.tt.style.opacity=1;this.tt.style.filter="alpha(opacity=1)";this.tt.style.position="absolute";this.tt.style.display="block";this.tt.style.overflow="hidden";this.parent.appendChild(this.tt)}if(this.lastlbl!==f){this.cont.innerHTML=f;this.lastlbl=f;this.tt.style.width="auto";if(a.browser.isIE){this.tt.style.width=this.tt.offsetWidth}}};this.hide=function(){if(this.tt!==null){this.parent.removeChild(this.tt)}this.tt=null;this.lastlbl=""};return this};a.Painter.CreateOrbitControl=function(u,q,s,o,v){var i=new THREE.OrbitControls(q,o.domElement);i.enableDamping=false;i.dampingFactor=1;i.enableZoom=true;if(v){i.target.copy(v);i.target0.copy(v);i.update()}var p={x:0,y:0,on:false},m=new THREE.Raycaster(),k=o instanceof THREE.WebGLRenderer,l=false,f=false,c=false,e=new a.Painter.TooltipFor3D(u.select_main().node(),o.domElement);i.ProcessMouseDblclick=function(){i.reset()};i.HideTooltip=function(){e.hide()};function h(x,w){w.x=("offsetX" in x)?x.offsetX:x.layerX;w.y=("offsetY" in x)?x.offsetY:x.layerY;w.clientX=x.clientX;w.clientY=x.clientY;return w}function n(w){var z=k?o.getSize():o.domElement;var y={x:w.x/z.width*2-1,y:-w.y/z.height*2+1};q.updateMatrix();q.updateMatrixWorld();m.setFromCamera(y,q);var x=m.intersectObjects(s.children,true);if(typeof u.FilterIntersects=="function"){x=u.FilterIntersects(x)}return x}i.addEventListener("change",function(){p.on=false;u.Render3D(0);f=true});i.addEventListener("start",function(){l=true;c=false;p.on=false;e.hide()});i.addEventListener("end",function(){l=false;if(p.on){p.on=false;i.ContextMenu(p,n(p))}else{if(f){}}f=false});function t(w){w.preventDefault();h(w,p);if(l){p.on=true}else{if(c){c=false}else{i.ContextMenu(p,n(p))}}}function j(w){if(!w.touches){return}if(!f&&!p.touchtm){h(w.touches[0],p);p.touchtm=new Date().getTime()}}function d(y){if(!y.touches){return}if(f||!p.touchtm){return}var w=new Date().getTime()-p.touchtm;delete p.touchtm;if(w<200){return}var x=h(y.touches[0],{});if((Math.abs(x.x-p.x)<=10)&&(Math.abs(x.y-p.y)<=10)){i.ContextMenu(p,n(p))}}i.ContextMenu=function(x,w){};function g(z){if(l&&z.buttons&&(z.buttons&2)){c=true}if(l||!i.ProcessMouseMove){return}var w=h(z,{});z.preventDefault();var x=n(w);var y=i.ProcessMouseMove(x);if(y&&(y.length>0)){e.show(y,200);e.pos(z)}else{e.hide()}}function r(){e.hide();if(i.ProcessMouseLeave){i.ProcessMouseLeave()}}o.domElement.addEventListener("dblclick",function(){i.ProcessMouseDblclick()});o.domElement.addEventListener("contextmenu",t);o.domElement.addEventListener("mousemove",g);o.domElement.addEventListener("mouseleave",r);return i};a.Painter.DisposeThreejsObject=function(d){if(!d){return}if(d.children){for(var c=0;ck.x2)||(k.y1>k.y2)||(k.z1>k.z2)){console.warn("check 3D hints coordinates")}k.x1-=l;k.x2+=l;k.y1-=l;k.y2+=l;k.z1-=l;k.z2+=l}d.BinHighlight3D(k);return(d.enable_tooltip&&k&&k.info)?k.info:""};this.control.ProcessMouseLeave=function(){d.BinHighlight3D(null)};this.control.ContextMenu=this.ShowContextMenu.bind(this,"hist")};a.Painter.HPainter_TestAxisVisibility=function(h,m,e,j){var l;for(var d=0;d=0)){i=2}if((k.x>=0)&&(k.y>=0)){i=3}if((k.x>=0)&&(k.y<0)){i=4}function f(p,n){if(p<=i){p+=4}return(p>i)&&(p0)){for(var ai=0;ai0){break}}}if(p<=0){p=0.0001*ab}this.tx=b.scale.log();this.x_kind="log"}else{this.tx=b.scale.linear();if(y&&y.fXaxis.fLabels){this.x_kind="labels"}else{this.x_kind="lin"}}this.tx.domain([p,ab]).range([H,g]);this.x_handle=new a.TAxisPainter(y?y.fXaxis:null);this.x_handle.SetAxisConfig("xaxis",this.x_kind,this.tx,this.xmin,this.xmax,p,ab);this.x_handle.CreateFormatFuncs();if(A&&A.fLogy&&!al){if(h<=0){h=1}if((V<=0)&&(this.nbinsy>0)){for(var ai=0;ai0){break}}}if(V<=0){V=0.0001*h}this.ty=b.scale.log();this.y_kind="log"}else{this.ty=b.scale.linear();if(y&&y.fYaxis.fLabels){this.y_kind="labels"}else{this.y_kind="lin"}}this.ty.domain([V,h]).range([G,f]);this.y_handle=new a.TAxisPainter(y?y.fYaxis:null);this.y_handle.SetAxisConfig("yaxis",this.y_kind,this.ty,this.ymin,this.ymax,V,h);this.y_handle.CreateFormatFuncs();if(A&&A.fLogz){if(M<=0){M=1}if(e<=0){e=0.0001*M}this.tz=b.scale.log();this.z_kind="log"}else{this.tz=b.scale.linear();this.z_kind="lin"}this.tz.domain([e,M]).range([D,d]);this.z_handle=new a.TAxisPainter(y?y.fZaxis:null);this.z_handle.SetAxisConfig("zaxis",this.z_kind,this.tz,this.zmin,this.zmax,e,M);this.z_handle.CreateFormatFuncs();var x=new THREE.MeshBasicMaterial({color:0}),s=new THREE.LineBasicMaterial({color:0}),Z=Y*0.5,N,c,L=[],I=1,X=this.x_handle.CreateTicks(),k=this.y_handle.CreateTicks(),aa=this.z_handle.CreateTicks();var j=new THREE.Object3D();j.axis_draw=true;z.add(j);var ac=[],ak=0;while(X.next()){var U=X.grpos;var ag=(X.kind===1);var F=this.x_handle.format(X.tick,true,true);if(X.last_major()){F="x"}else{if(F===null){ag=false;F=""}}if(ag&&F&&(F.length>0)){var C=new THREE.TextGeometry(F,{font:a.threejs_font_helvetiker_regular,size:Y,height:0,curveSegments:10});C.computeBoundingBox();var u=C.boundingBox.max.x-C.boundingBox.min.x,t=C.boundingBox.max.y-C.boundingBox.min.y;C.translate(-u/2,0,0);ak=Math.max(ak,t);C.grx=U;L.push(C);if(!X.last_major()){var aj=(X.next_major_grpos()-U);if(u>0){I=Math.min(I,0.9*aj/u)}if(this.x_handle.IsCenterLabels()){C.grx+=aj/2}}}ac.push(U,0,0,U,(ag?-Z:-Z*0.6),0)}var q=new THREE.Geometry(),o=new THREE.Geometry();L.forEach(function(n){var i=new THREE.Matrix4();i.set(I,0,0,n.grx,0,I,0,-ak*I-1.5*Z,0,0,1,0);q.merge(n,i);i.set(-I,0,0,n.grx,0,I,0,-ak*I-1.5*Z,0,0,1,0);o.merge(n,i)});q=new THREE.BufferGeometry().fromGeometry(q);o=new THREE.BufferGeometry().fromGeometry(o);var af=new THREE.BufferGeometry();af.addAttribute("position",new THREE.BufferAttribute(new Float32Array(ac),3));var ad=new THREE.Object3D();ad.position.set(0,G,D);ad.rotation.x=1/4*Math.PI;ad.xyid=2;ad.add(new THREE.LineSegments(af,s));ad.add(new THREE.Mesh(q,x));j.add(ad);ad=new THREE.Object3D();ad.position.set(0,f,D);ad.rotation.x=3/4*Math.PI;ad.add(new THREE.LineSegments(af,s));ad.add(new THREE.Mesh(o,x));ad.xyid=4;j.add(ad);L=[];I=1;ak=0;ac=[];while(k.next()){var T=k.grpos;var ag=(k.kind===1);var F=this.y_handle.format(k.tick,true,true);if(k.last_major()){F="y"}else{if(F===null){ag=false;F=""}}if(ag){var C=new THREE.TextGeometry(F,{font:a.threejs_font_helvetiker_regular,size:Y,height:0,curveSegments:10});C.computeBoundingBox();var u=C.boundingBox.max.x-C.boundingBox.min.x,t=C.boundingBox.max.y-C.boundingBox.min.y;C.translate(-u/2,0,0);ak=Math.max(ak,t);C.gry=T;L.push(C);if(!k.last_major()){var aj=(k.next_major_grpos()-T);if(u>0){I=Math.min(I,0.9*aj/u)}if(this.y_handle.IsCenterLabels()){C.gry+=aj/2}}}ac.push(0,T,0,(ag?-Z:-Z*0.6),T,0)}var q=new THREE.Geometry(),o=new THREE.Geometry();L.forEach(function(n){var i=new THREE.Matrix4();i.set(0,I,0,-ak*I-1.5*Z,-I,0,0,n.gry,0,0,1,0);q.merge(n,i);i.set(0,I,0,-ak*I-1.5*Z,I,0,0,n.gry,0,0,1,0);o.merge(n,i)});q=new THREE.BufferGeometry().fromGeometry(q);o=new THREE.BufferGeometry().fromGeometry(o);var af=new THREE.BufferGeometry();af.addAttribute("position",new THREE.BufferAttribute(new Float32Array(ac),3));if(!al){var O=new THREE.Object3D();O.position.set(H,0,D);O.rotation.y=-1/4*Math.PI;O.add(new THREE.LineSegments(af,s));O.add(new THREE.Mesh(q,x));O.xyid=3;j.add(O);O=new THREE.Object3D();O.position.set(g,0,D);O.rotation.y=-3/4*Math.PI;O.add(new THREE.LineSegments(af,s));O.add(new THREE.Mesh(o,x));O.xyid=1;j.add(O)}L=[];I=1;var ac=[];var K=null,J=null,am=null;if(this.size3d!==0){K=[];J=[]}while(aa.next()){var S=aa.grpos;var ag=aa.kind==1;var F=this.z_handle.format(aa.tick,true,true);if(F===null){ag=false;F=""}if(ag&&F&&(F.length>0)){var C=new THREE.TextGeometry(F,{font:a.threejs_font_helvetiker_regular,size:Y,height:0,curveSegments:10});C.computeBoundingBox();var u=C.boundingBox.max.x-C.boundingBox.min.x,t=C.boundingBox.max.y-C.boundingBox.min.y;C.translate(-u,-t/2,0);C.grz=S;L.push(C);if((am!==null)&&(t>0)){I=Math.min(I,0.9*(S-am)/t)}am=S}if(K&&ag){K.push(H,0,S,g,0,S)}if(J&&ag){J.push(0,G,S,0,f,S)}ac.push(0,0,S,(ag?Z:Z*0.6),0,S)}if(K&&(K.length>0)){var ah=new THREE.LineDashedMaterial({color:0,dashSize:10,gapSize:2});var m=new THREE.BufferGeometry();m.addAttribute("position",new THREE.BufferAttribute(new Float32Array(K),3));var W=new THREE.LineSegments(m,ah);W.position.set(0,f,0);W.grid=2;W.visible=false;j.add(W);W=new THREE.LineSegments(m,ah);W.position.set(0,G,0);W.grid=4;W.visible=false;j.add(W)}if(J&&(J.length>0)){var ah=new THREE.LineDashedMaterial({color:0,dashSize:10,gapSize:2});var m=new THREE.BufferGeometry();m.addAttribute("position",new THREE.BufferAttribute(new Float32Array(J),3));var W=new THREE.LineSegments(m,ah);W.position.set(g,0,0);W.grid=3;W.visible=false;j.add(W);W=new THREE.LineSegments(m,ah);W.position.set(H,0,0);W.grid=1;W.visible=false;j.add(W)}var E=new THREE.Geometry();L.forEach(function(n){var i=new THREE.Matrix4();i.set(-I,0,0,2*Z,0,0,1,0,0,I,0,n.grz);E.merge(n,i)});E=new THREE.BufferGeometry().fromGeometry(E);var af=new THREE.BufferGeometry();af.addAttribute("position",new THREE.BufferAttribute(new Float32Array(ac),3));var v=[];for(var ae=0;ae<4;++ae){v.push(new THREE.Object3D());v[ae].add(new THREE.Mesh(E,x));v[ae].add(new THREE.LineSegments(af,s));v[ae].zid=ae+2;j.add(v[ae])}v[0].position.set(H,f,0);v[0].rotation.z=3/4*Math.PI;v[1].position.set(g,f,0);v[1].rotation.z=1/4*Math.PI;v[2].position.set(g,G,0);v[2].rotation.z=-1/4*Math.PI;v[3].position.set(H,G,0);v[3].rotation.z=-3/4*Math.PI;if(this.size3d===0){return}var R=new THREE.BufferGeometry();R.addAttribute("position",new THREE.BufferAttribute(new Float32Array([H,0,0,g,0,0]),3));for(var ae=0;ae<2;++ae){var l=new THREE.LineSegments(R,s);l.position.set(0,G,(ae===0)?D:d);l.xyboxid=2;l.bottom=(ae==0);j.add(l);l=new THREE.LineSegments(R,s);l.position.set(0,f,(ae===0)?D:d);l.xyboxid=4;l.bottom=(ae==0);j.add(l)}var Q=new THREE.BufferGeometry();Q.addAttribute("position",new THREE.BufferAttribute(new Float32Array([0,G,0,0,f,0]),3));for(var ae=0;ae<2;++ae){var l=new THREE.LineSegments(Q,s);l.position.set(H,0,(ae===0)?D:d);l.xyboxid=3;l.bottom=(ae==0);j.add(l);l=new THREE.LineSegments(Q,s);l.position.set(g,0,(ae===0)?D:d);l.xyboxid=1;l.bottom=(ae==0);j.add(l)}var P=new THREE.BufferGeometry();P.addAttribute("position",new THREE.BufferAttribute(new Float32Array([0,0,D,0,0,d]),3));for(var ae=0;ae<4;++ae){var l=new THREE.LineSegments(P,s);l.zboxid=v[ae].zid;l.position.copy(v[ae].position);j.add(l)}};a.Painter.Box_Vertices=[new THREE.Vector3(1,1,1),new THREE.Vector3(1,1,0),new THREE.Vector3(1,0,1),new THREE.Vector3(1,0,0),new THREE.Vector3(0,1,0),new THREE.Vector3(0,1,1),new THREE.Vector3(0,0,0),new THREE.Vector3(0,0,1)];a.Painter.Box_Indexes=[0,2,1,2,3,1,4,6,5,6,7,5,4,5,1,5,0,1,7,6,2,6,3,2,5,7,0,7,2,0,1,3,4,3,6,4];a.Painter.Box_Normals=[1,0,0,-1,0,0,0,1,0,0,-1,0,0,0,1,0,0,-1];a.Painter.Box_Segments=[0,2,2,7,7,5,5,0,1,3,3,6,6,4,4,1,1,0,3,2,6,7,4,5];a.Painter.Box_MeshSegments=(function(){var c=new Int32Array(a.Painter.Box_Segments.length);for(var e=0;e0),aB=this.Dimension();var ad=this.GetSelectIndex("x","left",0),ac=this.GetSelectIndex("x","right",1),T=(aB===1)?0:this.GetSelectIndex("y","left",0),S=(aB===1)?1:this.GetSelectIndex("y","right",1),L,K,x,w,l,h,aj,Z,ae,at,r=this.main_painter(),U=(this.options.Lego===11)||(this.options.Lego===13);var ap=new Float32Array(ac+1),ah=new Float32Array(S+1);for(L=ad;L<=ac;++L){x=this.GetBinX(L);if(r.logx&&(x<=0)){ad=L+1;continue}ap[L]=this.tx(x);if(ap[L]<-1.001*this.size3d){ad=L+1}if(ap[L]>1.001*this.size3d){ac=L-1}}if(aB===1){ah[0]=this.ty(0);ah[1]=this.ty(1)}else{for(K=T;K<=S;++K){l=this.GetBinY(K);if(r.logy&&(l<=0)){T=K+1;continue}ah[K]=this.ty(l);if(ah[K]<-1.001*this.size3d){T=K+1}if(ah[K]>1.001*this.size3d){S=K-1}}}if((ad>=ac)||(T>=S)){return}var E=(this.histo.getBin(ac,S)<65535);var Y=[ax,q],M=null,am=0;if((this.options.Lego===12)||(this.options.Lego===14)){var d=20;if(this.histo.fContour!=null){d=this.histo.fContour.length}Y=this.CreateContour(d,this.lego_zmin,this.lego_zmax);M=this.GetPalette()}for(var ak=0;ak0)||!ar)){continue}ae=!Z&&(ak>0);at=!Z&&(aj>F)&&(ak0){P=new Float32Array(t*3);ab=new Float32Array(t*3);s=E?new Uint16Array(t):new Uint32Array(t)}for(L=ad;L0)||!ar)){continue}ae=!Z&&(ak>0);at=!Z&&(aj>F)&&(akF)?ag:this.tz(aj);W=0;J=0;if(Z){W+=12;J+=24}var D=H.length,e=this.histo.getBin(L+1,K+1);if(ae){D-=6}while(JM.length-1){I=M.length-1}o=M[I]}var aA=new THREE.MeshBasicMaterial({color:o,shading:THREE.SmoothShading});var O=new THREE.Mesh(af,aA);O.bins_index=aa;O.painter=this;O.zmin=ax;O.zmax=q;O.tip_color=(ai===3)?16711680:65280;O.tooltip=function(i){if((i.index<0)||(i.index>=this.bins_index.length)){return null}var k=this.painter,j=k.Get3DToolTip(this.bins_index[i.index]);j.x1=k.tx(k.GetBinX(j.ix-1));j.x2=k.tx(k.GetBinX(j.ix));if(k.Dimension()===1){j.y1=k.ty(0);j.y2=k.ty(1)}else{j.y1=k.ty(k.GetBinY(j.iy-1));j.y2=k.ty(k.GetBinY(j.iy))}j.z1=k.tz(this.zmin);j.z2=k.tz(this.zmax);if(j.value0){var al=new THREE.BufferGeometry();al.addAttribute("position",new THREE.BufferAttribute(P,3));al.addAttribute("normal",new THREE.BufferAttribute(ab,3));var ao=new THREE.MeshBasicMaterial({color:16711680,shading:THREE.SmoothShading});var z=new THREE.Mesh(al,ao);z.bins_index=s;z.painter=this;z.tooltip=O.tooltip;z.zmin=O.zmin;z.zmax=O.zmax;z.tip_color=O.tip_color;this.toplevel.add(z)}}if(this.options.Lego>12){return}var az=0,B=0,R=true;for(L=ad;L65520){R=false}if(!R){az=B*3}var u=new Float32Array(az*3),f=R?new Uint16Array(B):null;var ay=this.tz(ax),ag=this.tz(q),aw=0,aq=0,G=0;for(L=ad;LF)?ag:this.tz(aj);var N=Z?A:av,Q=Z?aD:V;if(R){for(J=0;J0)&&((this.options.Lego===12)||(this.options.Lego===14)));this.DrawTitle();a.CallBack(d)};a.Painter.TH2Painter_Draw3D=function(d,c){if(c){this.Resize3D()}else{this.Create3DScene();this.Draw3DBins=a.Painter.HistPainter_DrawLego;var e=this.root_pad();this.zmin=e.fLogz?this.gmin0bin*0.3:this.gminbin;this.zmax=this.gmaxbin;if(this.histo.fMinimum!==-1111){this.zmin=this.histo.fMinimum}if(this.histo.fMaximum!==-1111){this.zmax=this.histo.fMaximum}if(e.fLogz&&(this.zmin<=0)){this.zmin=this.zmax*0.00001}this.DeleteAtt();this.DrawXYZ(this.toplevel,false,1.1);this.Draw3DBins();this.Render3D()}this.DrawColorPalette((this.options.Zscale>0)&&((this.options.Lego===12)||(this.options.Lego===14)));this.DrawTitle();a.CallBack(d)};a.TH3Painter=function(c){a.THistPainter.call(this,c);this.Create3DScene=a.Painter.HPainter_Create3DScene};a.TH3Painter.prototype=Object.create(a.THistPainter.prototype);a.TH3Painter.prototype.ScanContent=function(){var d=this.GetObject();this.nbinsx=d.fXaxis.fNbins;this.nbinsy=d.fYaxis.fNbins;this.nbinsz=d.fZaxis.fNbins;this.xmin=d.fXaxis.fXmin;this.xmax=d.fXaxis.fXmax;this.ymin=d.fYaxis.fXmin;this.ymax=d.fYaxis.fXmax;this.zmin=d.fZaxis.fXmin;this.zmax=d.fZaxis.fXmax;this.gminbin=this.gmaxbin=d.getBinContent(1,1,1);var f,e,c;for(f=0;fthis.gmaxbin){this.gmaxbin=g}}}}}this.draw_content=this.gmaxbin>0;this.CreateAxisFuncs(true,true)};a.TH3Painter.prototype.CountStat=function(){var q=this.GetObject(),i=0,p=0,w=0,f=0,m=0,u=0,e=0,v=this.GetSelectIndex("x","left"),t=this.GetSelectIndex("x","right"),d=this.GetSelectIndex("y","left"),c=this.GetSelectIndex("y","right"),o=this.GetSelectIndex("z","left"),l=this.GetSelectIndex("z","right"),A={entries:0,integral:0,meanx:0,meany:0,meanz:0,rmsx:0,rmsy:0,rmsz:0};for(var s=0;st?2:1);for(var z=0;zc?2:1);for(var j=0;jl?2:1);var g=q.getBinContent(s,z,j);A.entries+=g;if((h==1)&&(x==1)&&(n==1)){i+=g;p+=k*g;w+=r*g;f+=y*g;m+=k*k*g;u+=r*r*g;e+=y*y*g}}}}if(q.fTsumw>0){i=q.fTsumw;p=q.fTsumwx;m=q.fTsumwx2;w=q.fTsumwy;u=q.fTsumwy2;f=q.fTsumwz;e=q.fTsumwz2}if(i>0){A.meanx=p/i;A.meany=w/i;A.meanz=f/i;A.rmsx=Math.sqrt(m/i-A.meanx*A.meanx);A.rmsy=Math.sqrt(u/i-A.meany*A.meany);A.rmsz=Math.sqrt(e/i-A.meanz*A.meanz)}A.integral=i;if(q.fEntries>1){A.entries=q.fEntries}return A};a.TH3Painter.prototype.FillStatistic=function(g,i,p){if(this.GetObject()===null){return false}var h=g.GetObject(),f=this.CountStat(),k=i%10,n=Math.floor(i/10)%10,j=Math.floor(i/100)%10,m=Math.floor(i/1000)%10,c=Math.floor(i/10000)%10,d=Math.floor(i/100000)%10,e=Math.floor(i/1000000)%10;if(k>0){h.AddText(this.GetObject().fName)}if(n>0){h.AddText("Entries = "+g.Format(f.entries,"entries"))}if(j>0){h.AddText("Mean x = "+g.Format(f.meanx));h.AddText("Mean y = "+g.Format(f.meany));h.AddText("Mean z = "+g.Format(f.meanz))}if(m>0){h.AddText("Std Dev x = "+g.Format(f.rmsx));h.AddText("Std Dev y = "+g.Format(f.rmsy));h.AddText("Std Dev z = "+g.Format(f.rmsz))}if(e>0){h.AddText("Integral = "+g.Format(f.integral,"entries"))}var l=h.fLines.arr.length,o=l*a.gStyle.StatFontSize;if(o<=0||3==(a.gStyle.StatFont%10)){o=0.25*l*a.gStyle.StatH;h.fY1NDC=0.93-o;h.fY2NDC=0.93}return true};a.TH3Painter.prototype.GetBinTips=function(e,c,f){var d=[];d.push(this.GetTipName());d.push("x="+a.FFormat(this.GetBinX(e+0.5),"6.4g")+" bin="+(e+1));d.push("y="+a.FFormat(this.GetBinY(c+0.5),"6.4g")+" bin="+(c+1));d.push("z="+a.FFormat(this.GetBinZ(f+0.5),"6.4g")+" bin="+(f+1));d.push("entries="+a.FFormat(this.GetObject().getBinContent(e+1,c+1,f+1),"7.0g"));return d};a.TH3Painter.prototype.Draw3DBins=function(){if(!this.draw_content){return}var af=this.GetObject().fFillColor,q=a.Painter.root_colors[af],W=null,S=0,r=null,d=0,A,ag;if(this.options.Box===11){W=new THREE.MeshLambertMaterial({color:q});var p=a.Painter.TestWebGL()?new THREE.SphereGeometry(0.5,16,12):new THREE.SphereGeometry(0.5,8,6);p.applyMatrix(new THREE.Matrix4().makeRotationX(Math.PI/2));S=p.faces.length*9;A=new Float32Array(S);ag=new Float32Array(S);for(var s=0;s");var z=(this.tx(this.GetBinX(m+0.5))-this.tx(this.GetBinX(o+0.5)))/(m-o),y=(this.ty(this.GetBinY(Z+0.5))-this.ty(this.GetBinY(ac+0.5)))/(Z-ac),x=(this.tz(this.GetBinZ(G+0.5))-this.tz(this.GetBinZ(H+0.5)))/(G-H);var V=0,ab,Y,X,g,e;for(ab=o;ab0)?1:e/this.gmaxbin;if(g<0.00001){continue}V++}}}if((d===1)&&(V*S/3>65520)){d=2}var h=new Float32Array(V*S),O=new Float32Array(V*S),P=new Int32Array(V),T,R,l;if(d===1){T=a.Painter.Box_MeshSegments;R=new Uint16Array(V*T.length)}if(d===2){T=a.Painter.Box_Segments;l=new Float32Array(V*T.length*3)}var ae,L,ad,K,aa,J;V=0;for(ab=o;ab=this.bins.length)){return null}var n=this.painter,k=n.Get3DToolTip(this.bins[j]);L=n.tx(n.GetBinX(k.ix-0.5));K=n.ty(n.GetBinY(k.iy-0.5));J=n.tz(n.GetBinZ(k.iz-0.5));g=k.value/n.gmaxbin;k.x1=L-this.scalex*g;k.x2=L+this.scalex*g;k.y1=K-this.scaley*g;k.y2=K+this.scaley*g;k.z1=J-this.scalez*g;k.z2=J+this.scalez*g;k.color=this.tip_color;return k};this.toplevel.add(u);if(d>0){var E=new THREE.BufferGeometry();if(d===1){E.setIndex(new THREE.BufferAttribute(R,1));E.addAttribute("position",new THREE.BufferAttribute(h,3))}else{E.addAttribute("position",new THREE.BufferAttribute(l,3))}var D=new THREE.LineBasicMaterial({color:0});var M=new THREE.LineSegments(E,D);this.toplevel.add(M)}};a.TH3Painter.prototype.Redraw=function(c){if(c){this.Resize3D()}else{this.Create3DScene();this.DrawXYZ(this.toplevel);this.Draw3DBins();this.Render3D()}};a.TH3Painter.prototype.FillToolbar=function(){var c=this.pad_painter(true);if(c===null){return}c.AddButton(a.ToolbarIcons.undo,"Unzoom all axes","UnzoomAllAxis");if(this.draw_content){c.AddButton(a.ToolbarIcons.statbox,"Toggle stat box","ToggleStatBox")}};a.TH3Painter.prototype.FillHistContextMenu=function(c){c.addDrawMenu("Draw with",["box","box1"],function(d){this.options=this.DecodeOptions(d);this.Redraw()})};a.Painter.drawHistogram3D=function(f,c,e){a.extend(this,new a.TH3Painter(c));this.SetDivId(f,4);this.options=this.DecodeOptions(e);this.CheckPadRange();this.ScanContent();this.Redraw();this.DrawTitle();if(a.gStyle.AutoStat&&this.create_canvas){var d=this.CreateStat();if(d){a.draw(this.divid,d,"")}}this.FillToolbar();return this.DrawingReady()};a.Painter.drawPolyMarker3D=function(j,l,d){this.SetDivId(j);var p=this.main_painter();if(!p||!("renderer" in p)){return this.DrawingReady()}var q=3,v=p.webgl?50000:5000;if((a.gStyle.OptimizeDraw>0)&&(l.fP.length>3*v)){q=Math.floor(l.fP.length/v/3)*3;if(q<=6){q=6}}var w=Math.floor(l.fP.length/q),e=a.Painter.Box_Indexes,A=a.Painter.Box_Normals,o=a.Painter.Box_Vertices,n=new Float32Array(e.length*3*w),m=new Float32Array(e.length*3*w),h=0,F=p.size3d/100;for(var D=0;D=this.poly.fP.length)){return null}var H=this.painter;var G={info:"bin: "+z/3+"
x: "+H.x_handle.format(this.poly.fP[z])+"
y: "+H.y_handle.format(this.poly.fP[z+1])+"
z: "+H.z_handle.format(this.poly.fP[z+2])};var y=H.tx(this.poly.fP[z]),x=H.ty(this.poly.fP[z+1]),k=H.tz(this.poly.fP[z+2]);G.x1=y-this.scale0;G.x2=y+this.scale0;G.y1=x-this.scale0;G.y2=x+this.scale0;G.z1=k-this.scale0;G.z2=k+this.scale0;G.color=this.tip_color;return G};p.Render3D(100);return this.DrawingReady()};return a.Painter})); \ No newline at end of file diff --git a/visualisations/JsRoot460/scripts/JSRootCore.js b/visualisations/JsRoot460/scripts/JSRootCore.js new file mode 100644 index 0000000..5cc7633 --- /dev/null +++ b/visualisations/JsRoot460/scripts/JSRootCore.js @@ -0,0 +1,1618 @@ +/** @file JSRootCore.js + * Core methods of JavaScript ROOT */ + +/** @namespace JSROOT + * Holder of all JSROOT functions and classes */ + +(function( factory ) { + if ( typeof define === "function" && define.amd ) { + + var jsroot = factory({}); + + var dir = jsroot.source_dir + "scripts/", ext = jsroot.source_min ? ".min" : ""; + + var paths = { + 'd3' : dir+'d3.v3.min', + 'jquery' : dir+'jquery.min', + 'jquery-ui' : dir+'jquery-ui.min', + 'jqueryui-mousewheel' : dir+'jquery.mousewheel'+ext, + 'jqueryui-touch-punch' : dir+'touch-punch.min', + 'rawinflate' : dir+'rawinflate'+ext, + 'MathJax' : 'https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_SVG&delayStartupUntil=configured', + 'saveSvgAsPng' : dir+'saveSvgAsPng'+ext, + 'dat.gui' : dir+'dat.gui.min', + 'threejs' : dir+'three', + 'threejs_all' : dir+'three.extra'+ext, + 'JSRootCore' : dir+'JSRootCore'+ext, + 'JSRootMath' : dir+'JSRootMath'+ext, + 'JSRootInterface' : dir+'JSRootInterface'+ext, + 'JSRootIOEvolution' : dir+'JSRootIOEvolution'+ext, + 'JSRootPainter' : dir+'JSRootPainter'+ext, + 'JSRootPainter.more' : dir+'JSRootPainter.more'+ext, + 'JSRootPainter.jquery' : dir+'JSRootPainter.jquery'+ext, + 'JSRoot3DPainter' : dir+'JSRoot3DPainter'+ext, + 'ThreeCSG' : dir+'ThreeCSG'+ext, + 'JSRootGeoBase' : dir+'JSRootGeoBase'+ext, + 'JSRootGeoPainter' : dir+'JSRootGeoPainter'+ext + }; + + var cfg_paths; + if ((requirejs.s!==undefined) && (requirejs.s.contexts !== undefined) && ((requirejs.s.contexts._!==undefined) && + requirejs.s.contexts._.config!==undefined)) cfg_paths = requirejs.s.contexts._.config.paths; + else console.warn("Require.js paths changed - please contact JSROOT developers"); + + // check if modules are already loaded + for (var module in paths) + if (requirejs.defined(module) || (cfg_paths && (module in cfg_paths))) + delete paths[module]; + + // configure all dependencies + requirejs.config({ + paths: paths, + shim: { + 'jqueryui-mousewheel': { deps: ['jquery-ui'] }, + 'jqueryui-touch-punch': { deps: ['jquery-ui'] }, + 'threejs_all': { deps: [ 'threejs'] }, + 'ThreeCSG' : { deps: [ 'threejs'] }, + 'MathJax': { + exports: 'MathJax', + init: function () { + MathJax.Hub.Config({ TeX: { extensions: ["color.js"] }}); + MathJax.Hub.Register.StartupHook("SVG Jax Ready",function () { + var VARIANT = MathJax.OutputJax.SVG.FONTDATA.VARIANT; + VARIANT["normal"].fonts.unshift("MathJax_SansSerif"); + VARIANT["bold"].fonts.unshift("MathJax_SansSerif-bold"); + VARIANT["italic"].fonts.unshift("MathJax_SansSerif"); + VARIANT["-tex-mathit"].fonts.unshift("MathJax_SansSerif"); + }); + MathJax.Hub.Startup.onload(); + return MathJax; + } + } + } + }); + + // AMD. Register as an anonymous module. + define( jsroot ); + + if (!require.specified("JSRootCore")) + define('JSRootCore', [], jsroot); + + if (!require.specified("jsroot")) + define('jsroot', [], jsroot); + + } else { + + if (typeof JSROOT != 'undefined') + throw new Error("JSROOT is already defined", "JSRootCore.js"); + + JSROOT = {}; + + factory(JSROOT); + } +} (function(JSROOT) { + + JSROOT.version = "4.6.0 22/08/2016"; + + JSROOT.source_dir = ""; + JSROOT.source_min = false; + JSROOT.source_fullpath = ""; // full name of source script + JSROOT.bower_dir = ""; // when specified, use standard libs from bower location + + JSROOT.id_counter = 0; + + JSROOT.touches = false; + JSROOT.browser = { isOpera:false, isFirefox:true, isSafari:false, isChrome:false, isIE:false }; + + if ((typeof document !== "undefined") && (typeof window !== "undefined")) { + var scripts = document.getElementsByTagName('script'); + for (var n = 0; n < scripts.length; ++n) { + var src = scripts[n].src; + if ((src===undefined) || (typeof src !== 'string')) continue; + + var pos = src.indexOf("scripts/JSRootCore."); + if (pos<0) continue; + + JSROOT.source_dir = src.substr(0, pos); + JSROOT.source_min = src.indexOf("scripts/JSRootCore.min.js") >= 0; + + JSROOT.source_fullpath = src; + + if ((console!==undefined) && (typeof console.log == 'function')) + console.log("Set JSROOT.source_dir to " + JSROOT.source_dir + ", " + JSROOT.version); + break; + } + + JSROOT.touches = ('ontouchend' in document); // identify if touch events are supported + JSROOT.browser.isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0; + JSROOT.browser.isFirefox = typeof InstallTrigger !== 'undefined'; + JSROOT.browser.isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0; + JSROOT.browser.isChrome = !!window.chrome && !JSROOT.browser.isOpera; + JSROOT.browser.isIE = false || !!document.documentMode; + } + + JSROOT.browser.isWebKit = JSROOT.browser.isChrome || JSROOT.browser.isSafari; + + // default draw styles, can be changed after loading of JSRootCore.js + JSROOT.gStyle = { + Tooltip : 1, // 0 - off, 1 - on + ContextMenu : true, + Zooming : true, + MoveResize : true, // enable move and resize of elements like statbox, title, pave, colz + DragAndDrop : true, // enables drag and drop functionality + ToolBar : true, // show additional tool buttons on the canvas + OptimizeDraw : 1, // drawing optimization: 0 - disabled, 1 - only for large (>5000 1d bins, >50 2d bins) histograms, 2 - always + AutoStat : true, + OptStat : 1111, + OptFit : 0, + FrameNDC : { fX1NDC: 0.07, fY1NDC: 0.12, fX2NDC: 0.95, fY2NDC: 0.88 }, + StatNDC : { fX1NDC: 0.78, fY1NDC: 0.75, fX2NDC: 0.98, fY2NDC: 0.91 }, + StatText : { fTextAngle: 0, fTextSize: 9, fTextAlign: 12, fTextColor: 1, fTextFont: 42 }, + StatFill : { fFillColor: 0, fFillStyle: 1001 }, + TimeOffset : 788918400000, // UTC time at 01/01/95 + StatFormat : "6.4g", + FitFormat : "5.4g", + Palette : 57, + MathJax : 0, // 0 - never, 1 - only for complex cases, 2 - always + ProgressBox : true, // show progress box + Embed3DinSVG : 2, // 0 - no embed, only 3D plot, 1 - overlay over SVG (IE/WebKit), 2 - embed into SVG (only Firefox) + NoWebGL : false, // if true, WebGL will be disabled, + EndErrorSize : 2, // size in pixels of end error for E1 draw options + GeoGradPerSegm : 6, // amount of grads per segment in TGeo spherical shapes like tube + GeoCompressComp : true // if one should compress faces after creation of composite shape + }; + + JSROOT.BIT = function(n) { return 1 << (n); } + + // TH1 status bits + JSROOT.TH1StatusBits = { + kNoStats : JSROOT.BIT(9), // don't draw stats box + kUserContour : JSROOT.BIT(10), // user specified contour levels + kCanRebin : JSROOT.BIT(11), // can rebin axis + kLogX : JSROOT.BIT(15), // X-axis in log scale + kIsZoomed : JSROOT.BIT(16), // bit set when zooming on Y axis + kNoTitle : JSROOT.BIT(17), // don't draw the histogram title + kIsAverage : JSROOT.BIT(18) // Bin contents are average (used by Add) + }; + + JSROOT.EAxisBits = { + kTickPlus : JSROOT.BIT(9), + kTickMinus : JSROOT.BIT(10), + kAxisRange : JSROOT.BIT(11), + kCenterTitle : JSROOT.BIT(12), + kCenterLabels : JSROOT.BIT(14), + kRotateTitle : JSROOT.BIT(15), + kPalette : JSROOT.BIT(16), + kNoExponent : JSROOT.BIT(17), + kLabelsHori : JSROOT.BIT(18), + kLabelsVert : JSROOT.BIT(19), + kLabelsDown : JSROOT.BIT(20), + kLabelsUp : JSROOT.BIT(21), + kIsInteger : JSROOT.BIT(22), + kMoreLogLabels : JSROOT.BIT(23), + kDecimals : JSROOT.BIT(11) + }; + + // wrapper for console.log, avoids missing console in IE + // if divid specified, provide output to the HTML element + JSROOT.console = function(value, divid) { + if ((divid!=null) && (typeof divid=='string') && ((typeof document.getElementById(divid))!='undefined')) + document.getElementById(divid).innerHTML = value; + else + if ((typeof console != 'undefined') && (typeof console.log == 'function')) + console.log(value); + } + + // extract reference, coded inside string + // check already should be done, that string starts from "$ref:" + JSROOT.JSONR_unref_str = function(value, dy) { + // if ((value.length > 5) && (value.indexOf("$ref:") === 0)) + var i = parseInt(value.substr(5)); + return (!isNaN(i) && (i >= 0) && (i < dy.length)) ? dy[i] : value; + } + + // replace all references inside object + // object should not be null + // This is part of the JSON-R code, found on + // https://github.com/graniteds/jsonr + // Only unref part was used, arrays are not accounted as objects + JSROOT.JSONR_unref_obj = function(value, dy) { + var i, fld, proto = Object.prototype.toString.apply(value); + + if (proto === '[object Array]') { + for (i = 0; i < value.length; ++i) { + fld = value[i]; + if (typeof fld === 'string') { + if ((fld.length > 5) && (fld.indexOf("$ref:") === 0)) + value[i] = this.JSONR_unref_str(fld, dy); + } else + if ((typeof fld === 'object') && (fld !== null)) + this.JSONR_unref_obj(fld, dy); + } + return; + } + + // if object in the table, return it + if (dy.indexOf(value) >= 0) return; + + // add object to object map + dy.push(value); + + // add methods to all objects, where _typename is specified + if ('_typename' in value) this.addMethods(value); + + var ks = Object.keys(value); + for (var k = 0; k < ks.length; ++k) { + i = ks[k]; + fld = value[i]; + + if (typeof fld === 'string') { + if ((fld.length > 5) && (fld.indexOf("$ref:") === 0)) + value[i] = this.JSONR_unref_str(fld, dy); + } else + if ((typeof fld === 'object') && (fld !== null)) + this.JSONR_unref_obj(fld, dy); + } + + return value; + } + + /// Should be used to reintroduce objects references, produced by TBufferJSON + JSROOT.JSONR_unref = function(value) { + if ((typeof value === 'object') && (value !== null)) + this.JSONR_unref_obj(value, []); + return value; + } + + JSROOT.debug = 0; + + // This is simple replacement of jQuery.extend method + // Just copy (not clone) all fields from source to the target object + JSROOT.extend = function(tgt, src) { + if ((src === null) || (typeof src !== 'object')) return src; + if ((tgt === null) || (typeof tgt !== 'object')) tgt = {}; + + for (var k in src) + tgt[k] = src[k]; + + return tgt; + } + + // Make deep clone of the object, including all sub-objects + JSROOT.clone = function(src, map, nofunc) { + if (src === null) return null; + + if (!map) { + map = { obj:[], clones:[], nofunc: nofunc }; + } else { + var i = map.obj.indexOf(src); + if (i>=0) return map.clones[i]; + } + + var proto = Object.prototype.toString.apply(src); + + // process normal array + if (proto === '[object Array]') { + var tgt = []; + map.obj.push(src); + map.clones.push(tgt); + for (var i = 0; i < src.length; ++i) + if (typeof src[i] === 'object') + tgt.push(JSROOT.clone(src[i], map)); + else + tgt.push(src[i]); + + return tgt; + } + + // process typed array + if ((proto.indexOf('[object ') == 0) && (proto.indexOf('Array]') == proto.length-6)) { + var tgt = []; + map.obj.push(src); + map.clones.push(tgt); + for (var i = 0; i < src.length; ++i) + tgt.push(src[i]); + + return tgt; + } + + var tgt = {}; + map.obj.push(src); + map.clones.push(tgt); + + for (var k in src) { + if (typeof src[k] === 'object') + tgt[k] = JSROOT.clone(src[k], map); + else + if (!map.nofunc || (typeof src[k]!=='function')) + tgt[k] = src[k]; + } + + return tgt; + } + + // method can be used to delete all functions from objects + // only such objects can be cloned when transfer to Worker + JSROOT.clear_func = function(src, map) { + if (src === null) return src; + + var proto = Object.prototype.toString.apply(src); + + if (proto === '[object Array]') { + for (var n=0;n0) { + + if (url==opt) return ""; + + pos = url.indexOf("&"); + if (pos < 0) pos = url.length; + + if (url.indexOf(opt) == 0) { + if (url.charAt(opt.length)=="&") return ""; + + // replace several symbols which are known to make a problem + if (url.charAt(opt.length)=="=") + return url.slice(opt.length+1, pos).replace(/%27/g, "'").replace(/%22/g, '"').replace(/%20/g, ' ').replace(/%3C/g, '<').replace(/%3E/g, '>').replace(/%5B/g, '[').replace(/%5D/g, ']'); + } + + url = url.slice(pos+1); + } + return dflt; + } + + JSROOT.ParseAsArray = function(val) { + // parse string value as array. + // It could be just simple string: "value" + // or array with or without string quotes: [element], ['eleme1',elem2] + + var res = []; + + if (typeof val != 'string') return res; + + val = val.trim(); + if (val=="") return res; + + // return as array with single element + if ((val.length<2) || (val[0]!='[') || (val[val.length-1]!=']')) { + res.push(val); return res; + } + + // try to parse ourself + var arr = val.substr(1, val.length-2).split(","); // remove brackets + + for (var i = 0; i < arr.length; ++i) { + var sub = arr[i].trim(); + if ((sub.length>1) && (sub[0]==sub[sub.length-1]) && ((sub[0]=='"') || (sub[0]=="'"))) + sub = sub.substr(1, sub.length-2); + res.push(sub); + } + return res; + } + + JSROOT.GetUrlOptionAsArray = function(opt, url) { + // special handling of URL options to produce array + // if normal option is specified ...?opt=abc, than array with single element will be created + // one could specify normal JSON array ...?opt=['item1','item2'] + // but also one could skip quotes ...?opt=[item1,item2] + // one could collect values from several options, specifying + // options names via semicolon like opt='item;items' + + var res = []; + + while (opt.length>0) { + var separ = opt.indexOf(";"); + var part = separ>0 ? opt.substr(0, separ) : opt; + if (separ>0) opt = opt.substr(separ+1); else opt = ""; + + var val = this.GetUrlOption(part, url, null); + res = res.concat(JSROOT.ParseAsArray(val)); + } + return res; + } + + JSROOT.findFunction = function(name) { + if (typeof name === 'function') return name; + if (typeof window[name] == 'function') return window[name]; + if ((typeof name !== 'string') || (name.indexOf(".") < 0)) return null; + + var names = name.split('.'), elem = window; + for (var n=0;n + + function completeLoad() { + if (debugout) + document.getElementById(debugout).innerHTML = ""; + else + JSROOT.progress(); + + if ((urllist!=null) && (urllist.length>0)) + return JSROOT.loadScript(urllist, callback, debugout); + + JSROOT.CallBack(callback); + } + + if ((urllist==null) || (urllist.length==0)) + return completeLoad(); + + var filename = urllist; + var separ = filename.indexOf(";"); + if (separ>0) { + filename = filename.substr(0, separ); + urllist = urllist.slice(separ+1); + } else { + urllist = ""; + } + + var isrootjs = false, isbower = false; + if (filename.indexOf("$$$")===0) { + isrootjs = true; + filename = filename.slice(3); + if ((filename.indexOf("style/")==0) && JSROOT.source_min && + (filename.lastIndexOf('.css')==filename.length-3) && + (filename.indexOf('.min.css')<0)) + filename = filename.slice(0, filename.length-4) + '.min.css'; + } else + if (filename.indexOf("###")===0) { + isbower = true; + filename = filename.slice(3); + } + + var font_suffix = filename.indexOf('.typeface.json'); + if (font_suffix > 0) { + var fontid = 'threejs_font_' + filename.slice(filename.lastIndexOf('/')+1, font_suffix); + if (typeof JSROOT[fontid] !== 'undefined') return completeLoad(); + + if ((typeof THREE === 'undefined') || (typeof THREE.FontLoader === 'undefined')) { + console.log('fail to load',filename,'no (proper) three.js found'); + return completeLoad(); + } + + JSROOT.progress("loading " + filename + " ..."); + + var loader = new THREE.FontLoader(); + loader.load( filename, function ( response ) { + JSROOT[fontid] = response; + completeLoad(); + } ); + return; + } + + var isstyle = filename.indexOf('.css') > 0; + + if (isstyle) { + var styles = document.getElementsByTagName('link'); + for (var n = 0; n < styles.length; ++n) { + if ((styles[n].type != 'text/css') || (styles[n].rel !== 'stylesheet')) continue; + + var href = styles[n].href; + if ((href == null) || (href.length == 0)) continue; + + if (href.indexOf(filename)>=0) return completeLoad(); + } + + } else { + var scripts = document.getElementsByTagName('script'); + + for (var n = 0; n < scripts.length; ++n) { + // if (scripts[n].type != 'text/javascript') continue; + + var src = scripts[n].src; + if ((src == null) || (src.length == 0)) continue; + + if ((src.indexOf(filename)>=0) && (src.indexOf("load=")<0)) { + // avoid wrong decision when script name is specified as more argument + return completeLoad(); + } + } + } + + if (isrootjs && (JSROOT.source_dir!=null)) filename = JSROOT.source_dir + filename; else + if (isbower && (JSROOT.bower_dir.length>0)) filename = JSROOT.bower_dir + filename; + + var element = null; + + if (debugout) + document.getElementById(debugout).innerHTML = "loading " + filename + " ..."; + else + JSROOT.progress("loading " + filename + " ..."); + + if (isstyle) { + element = document.createElement("link"); + element.setAttribute("rel", "stylesheet"); + element.setAttribute("type", "text/css"); + element.setAttribute("href", filename); + } else { + element = document.createElement("script"); + element.setAttribute('type', "text/javascript"); + element.setAttribute('src', filename); + } + + if (element.readyState) { // Internet Explorer specific + element.onreadystatechange = function() { + if (element.readyState == "loaded" || element.readyState == "complete") { + element.onreadystatechange = null; + completeLoad(); + } + } + } else { // Other browsers + element.onload = function() { + element.onload = null; + completeLoad(); + } + } + + document.getElementsByTagName("head")[0].appendChild(element); + } + + JSROOT.AssertPrerequisites = function(kind, callback, debugout) { + // one could specify kind of requirements + // 'io' for I/O functionality (default) + // '2d' for basic 2d graphic (TCanvas, TH1) + // 'more2d' for extra 2d graphic (TH2, TGraph) + // 'jq' jQuery and jQuery-ui + // 'jq2d' jQuery-dependend part of 2d graphic + // '3d' for histograms 3d graphic + // 'geom' for geometry drawing support + // 'simple' for basic user interface + // 'load:' list of user-specific scripts at the end of kind string + + var jsroot = JSROOT; + + if (jsroot.doing_assert === undefined) jsroot.doing_assert = []; + if (jsroot.ready_modules === undefined) jsroot.ready_modules = []; + + if ((typeof kind !== 'string') || (kind == '')) + return jsroot.CallBack(callback); + + if (kind === '__next__') { + if (jsroot.doing_assert.length==0) return; + var req = jsroot.doing_assert[0]; + if (req.running) return; + kind = req._kind; + callback = req._callback; + debugout = req._debug; + } else { + jsroot.doing_assert.push({_kind:kind, _callback:callback, _debug: debugout}); + if (jsroot.doing_assert.length > 1) return; + } + + jsroot.doing_assert[0].running = true; + + if (kind.charAt(kind.length-1)!=";") kind+=";"; + + var ext = jsroot.source_min ? ".min" : "", + need_jquery = false, + use_bower = (jsroot.bower_dir.length > 0), + mainfiles = "", + extrafiles = "", // scripts for direct loadin + modules = []; // modules used for require.js + + if (kind.indexOf('io;')>=0) { + mainfiles += "$$$scripts/rawinflate" + ext + ".js;" + + "$$$scripts/JSRootIOEvolution" + ext + ".js;"; + modules.push('JSRootIOEvolution'); + } + + if (kind.indexOf('2d;')>=0) { + if (jsroot._test_d3_ === undefined) { + if (typeof d3 != 'undefined') { + jsroot.console('Reuse existing d3.js ' + d3.version + ", required 3.5.9", debugout); + jsroot._test_d3_ = 1; + } else { + mainfiles += use_bower ? '###d3/d3.min.js;' : '$$$scripts/d3.v3.min.js;'; + jsroot._test_d3_ = 2; + } + } + modules.push('JSRootPainter'); + mainfiles += '$$$scripts/JSRootPainter' + ext + ".js;"; + extrafiles += '$$$style/JSRootPainter' + ext + '.css;'; + } + + if (kind.indexOf('savepng;')>=0) { + modules.push('saveSvgAsPng'); + mainfiles += '$$$scripts/saveSvgAsPng' + ext + ".js;"; + } + + if (kind.indexOf('jq;')>=0) need_jquery = true; + + if (kind.indexOf('math;')>=0) { + mainfiles += '$$$scripts/JSRootMath' + ext + ".js;"; + modules.push('JSRootMath'); + } + + if (kind.indexOf('more2d;')>=0) { + mainfiles += '$$$scripts/JSRootPainter.more' + ext + ".js;"; + modules.push('JSRootPainter.more'); + } + + if (kind.indexOf('jq2d;')>=0) { + mainfiles += '$$$scripts/JSRootPainter.jquery' + ext + ".js;"; + modules.push('JSRootPainter.jquery'); + need_jquery = true; + } + + if ((kind.indexOf("3d;")>=0) || (kind.indexOf("geom;")>=0)) { + if (use_bower) { + mainfiles += "###threejs/build/three.min.js;" + + "###threejs/examples/js/renderers/Projector.js;" + + "###threejs/examples/js/renderers/CanvasRenderer.js;" + + "###threejs/examples/js/controls/OrbitControls.js;" + + "###threejs/examples/js/controls/TransformControls.js;" + + "###threejs/examples/js/shaders/CopyShader.js;" + + "###threejs/examples/js/postprocessing/EffectComposer.js;" + + "###threejs/examples/js/postprocessing/MaskPass.js;" + + "###threejs/examples/js/postprocessing/RenderPass.js;" + + "###threejs/examples/js/postprocessing/ShaderPass.js;" + + "###threejs/examples/js/shaders/SSAOShader.js;" + extrafiles += "###threejs/examples/fonts/helvetiker_regular.typeface.json;"; + } else { + mainfiles += "$$$scripts/three.js;" + + "$$$scripts/three.extra" + ext + ".js;"; + } + modules.push("threejs_all"); + mainfiles += "$$$scripts/JSRoot3DPainter" + ext + ".js;"; + modules.push('JSRoot3DPainter'); + } + + if (kind.indexOf("geom;")>=0) { + mainfiles += "$$$scripts/ThreeCSG" + ext + ".js;" + + "$$$scripts/JSRootGeoBase" + ext + ".js;" + + "$$$scripts/JSRootGeoPainter" + ext + ".js;" + + "$$$scripts/dat.gui.min.js;"; + extrafiles += "$$$style/JSRootGeoPainter" + ext + ".css;"; + modules.push('ThreeCSG', 'JSRootGeoBase', 'JSRootGeoPainter', 'dat.gui'); + } + + if (kind.indexOf("mathjax;")>=0) { + if (typeof MathJax == 'undefined') { + mainfiles += (use_bower ? "###MathJax/MathJax.js" : "https://cdn.mathjax.org/mathjax/latest/MathJax.js") + + "?config=TeX-AMS-MML_SVG," + jsroot.source_dir + "scripts/mathjax_config.js;"; + } + if (jsroot.gStyle.MathJax == 0) jsroot.gStyle.MathJax = 1; + modules.push('MathJax'); + } + + if (kind.indexOf("simple;")>=0) { + need_jquery = true; + mainfiles += '$$$scripts/JSRootInterface' + ext + ".js;"; + extrafiles += '$$$style/JSRootInterface' + ext + '.css;'; + modules.push('JSRootInterface'); + } + + if (need_jquery && !jsroot.load_jquery) { + var has_jq = (typeof jQuery != 'undefined'), lst_jq = ""; + + if (has_jq) + jsroot.console('Reuse existing jQuery ' + jQuery.fn.jquery + ", required 2.1.4", debugout); + else + lst_jq += (use_bower ? "###jquery/dist" : "$$$scripts") + "/jquery.min.js;"; + if (has_jq && typeof $.ui != 'undefined') + jsroot.console('Reuse existing jQuery-ui ' + $.ui.version + ", required 1.11.4", debugout); + else { + lst_jq += (use_bower ? "###jquery-ui" : "$$$scripts") + '/jquery-ui.min.js;'; + extrafiles += '$$$style/jquery-ui' + ext + '.css;'; + } + + if (jsroot.touches) { + lst_jq += use_bower ? '###jqueryui-touch-punch/jquery.ui.touch-punch.min.js;' : '$$$scripts/touch-punch.min.js;'; + modules.push('jqueryui-touch-punch'); + } + + modules.splice(0,0, 'jquery', 'jquery-ui', 'jqueryui-mousewheel'); + mainfiles = lst_jq + mainfiles; + + jsroot.load_jquery = true; + } + + var pos = kind.indexOf("user:"); + if (pos<0) pos = kind.indexOf("load:"); + if (pos>=0) extrafiles += kind.slice(pos+5); + + + function load_callback() { + var req = jsroot.doing_assert.shift(); + for (var n=0;n=0;--n) + if (jsroot.ready_modules.indexOf(modules[n])>=0) + modules.splice(n,1); + + // no modules means no main files + if (modules.length===0) mainfiles = ""; + + jsroot.doing_assert[0].modules = modules; + + if ((modules.length>0) && (typeof define === "function") && define.amd) { + jsroot.console("loading " + JSON.stringify(modules) + " with require.js", debugout); + require(modules, function() { + jsroot.loadScript(extrafiles, load_callback, debugout); + }); + } else { + jsroot.loadScript(mainfiles + extrafiles, load_callback, debugout); + } + } + + // function can be used to open ROOT file, I/O functionality will be loaded when missing + JSROOT.OpenFile = function(filename, callback) { + JSROOT.AssertPrerequisites("io", function() { + new JSROOT.TFile(filename, callback); + }); + } + + // function can be used to draw supported ROOT classes, + // required functionality will be loaded automatically + // if painter pointer required, one should load '2d' functionlity itself + JSROOT.draw = function(divid, obj, opt) { + JSROOT.AssertPrerequisites("2d", function() { + JSROOT.draw(divid, obj, opt); + }); + } + + JSROOT.redraw = function(divid, obj, opt) { + JSROOT.AssertPrerequisites("2d", function() { + JSROOT.redraw(divid, obj, opt); + }); + } + + JSROOT.BuildSimpleGUI = function(user_scripts, andThen) { + if (typeof user_scripts == 'function') { + andThen = user_scripts; + user_scripts = null; + } + + var debugout = null; + var nobrowser = JSROOT.GetUrlOption('nobrowser')!=null; + var requirements = "io;2d;"; + + if (document.getElementById('simpleGUI')) { + debugout = 'simpleGUI'; + if ((JSROOT.GetUrlOption('json')!=null) && + (JSROOT.GetUrlOption('file')==null) && + (JSROOT.GetUrlOption('files')==null)) requirements = "2d;"; + } else + if (document.getElementById('onlineGUI')) { debugout = 'onlineGUI'; requirements = "2d;"; } else + if (document.getElementById('drawGUI')) { debugout = 'drawGUI'; requirements = "2d;"; nobrowser = true; } + + if (user_scripts == 'check_existing_elements') { + user_scripts = null; + if (debugout == null) return; + } + + if (!nobrowser) requirements += 'jq2d;simple;'; + + if (user_scripts == null) user_scripts = JSROOT.GetUrlOption("autoload"); + if (user_scripts == null) user_scripts = JSROOT.GetUrlOption("load"); + + if (user_scripts != null) + requirements += "load:" + user_scripts + ";"; + + JSROOT.AssertPrerequisites(requirements, function() { + JSROOT.CallBack(JSROOT.findFunction(nobrowser ? 'JSROOT.BuildNobrowserGUI' : 'BuildSimpleGUI')); + JSROOT.CallBack(andThen); + }, debugout); + }; + + JSROOT.Create = function(typename, target) { + var obj = target; + if (obj == null) obj = { _typename: typename }; + + switch (typename) { + case 'TObject': + JSROOT.extend(obj, { fUniqueID: 0, fBits: 0x3000008 }); + break; + case 'TNamed': + JSROOT.extend(obj, { fUniqueID: 0, fBits: 0x3000008, fName: "", fTitle: "" }); + break; + case 'TList': + case 'THashList': + JSROOT.extend(obj, { name: typename, arr : [], opt : [] }); + break; + case 'TAttAxis': + JSROOT.extend(obj, { fNdivisions: 510, fAxisColor: 1, + fLabelColor: 1, fLabelFont: 42, fLabelOffset: 0.005, fLabelSize: 0.035, fTickLength: 0.03, + fTitleOffset: 1, fTitleSize: 0.035, fTitleColor: 1, fTitleFont : 42 }); + break; + case 'TAxis': + JSROOT.Create("TNamed", obj); + JSROOT.Create("TAttAxis", obj); + JSROOT.extend(obj, { fNbins: 0, fXmin: 0, fXmax: 0, fXbins : [], fFirst: 0, fLast: 0, + fBits2: 0, fTimeDisplay: false, fTimeFormat: "", fLabels: null }); + break; + case 'TAttLine': + JSROOT.extend(obj, { fLineColor: 1, fLineStyle : 1, fLineWidth : 1 }); + break; + case 'TAttFill': + JSROOT.extend(obj, { fFillColor: 0, fFillStyle : 0 } ); + break; + case 'TAttMarker': + JSROOT.extend(obj, { fMarkerColor: 1, fMarkerStyle : 1, fMarkerSize : 1. }); + break; + case 'TLine': + JSROOT.Create("TObject", obj); + JSROOT.Create("TAttLine", obj); + JSROOT.extend(obj, { fX1: 0, fX2: 1, fY1: 0, fY2: 1 }); + break; + case 'TBox': + JSROOT.Create("TObject", obj); + JSROOT.Create("TAttLine", obj); + JSROOT.Create("TAttFill", obj); + JSROOT.extend(obj, { fX1: 0, fX2: 1, fY1: 0, fY2: 1 }); + break; + case 'TPave': + JSROOT.Create("TBox", obj); + JSROOT.extend(obj, { fX1NDC : 0., fY1NDC: 0, fX2NDC: 1, fY2NDC: 1, + fBorderSize: 0, fInit: 1, fShadowColor: 1, + fCornerRadius: 0, fOption: "blNDC", fName: "title" }); + break; + case 'TAttText': + JSROOT.extend(obj, { fTextAngle: 0, fTextSize: 0, fTextAlign: 22, fTextColor: 1, fTextFont: 42}); + break; + case 'TPaveText': + JSROOT.Create("TPave", obj); + JSROOT.Create("TAttText", obj); + JSROOT.extend(obj, { fLabel: "", fLongest: 27, fMargin: 0.05, fLines: JSROOT.Create("TList") }); + break; + case 'TPaveStats': + JSROOT.Create("TPaveText", obj); + JSROOT.extend(obj, { fOptFit: 0, fOptStat: 0, fFitFormat: "", fStatFormat: "", fParent: null }); + break; + case 'TObjString': + JSROOT.Create("TObject", obj); + JSROOT.extend(obj, { fString: "" }); + break; + case 'TH1': + JSROOT.Create("TNamed", obj); + JSROOT.Create("TAttLine", obj); + JSROOT.Create("TAttFill", obj); + JSROOT.Create("TAttMarker", obj); + + JSROOT.extend(obj, { + fNcells : 0, + fXaxis: JSROOT.Create("TAxis"), + fYaxis: JSROOT.Create("TAxis"), + fZaxis: JSROOT.Create("TAxis"), + fBarOffset: 0, fBarWidth: 1000, fEntries: 0., + fTsumw: 0., fTsumw2: 0., fTsumwx: 0., fTsumwx2: 0., + fMaximum: -1111., fMinimum: -1111, fNormFactor: 0., fContour: [], + fSumw2: [], fOption: "", + fFunctions: JSROOT.Create("TList"), + fBufferSize: 0, fBuffer: [], fBinStatErrOpt: 0 }); + break; + case 'TH1I': + case 'TH1F': + case 'TH1D': + case 'TH1S': + case 'TH1C': + JSROOT.Create("TH1", obj); + obj.fArray = []; + break; + case 'TH2': + JSROOT.Create("TH1", obj); + JSROOT.extend(obj, { fScalefactor: 1., fTsumwy: 0., fTsumwy2: 0, fTsumwxy : 0}); + break; + case 'TH2I': + case 'TH2F': + case 'TH2D': + case 'TH2S': + case 'TH2C': + JSROOT.Create("TH2", obj); + obj.fArray = []; + break; + case 'TGraph': + JSROOT.Create("TNamed", obj); + JSROOT.Create("TAttLine", obj); + JSROOT.Create("TAttFill", obj); + JSROOT.Create("TAttMarker", obj); + JSROOT.extend(obj, { fFunctions: JSROOT.Create("TList"), fHistogram: null, + fMaxSize: 0, fMaximum:-1111, fMinimum:-1111, fNpoints: 0, fX: [], fY: [] }); + break; + case 'TMultiGraph': + JSROOT.Create("TNamed", obj); + JSROOT.extend(obj, { fFunctions: JSROOT.Create("TList"), fGraphs: JSROOT.Create("TList"), + fHistogram: null, fMaximum: -1111, fMinimum: -1111 }); + break; + case 'TGaxis': + JSROOT.Create("TLine", obj); + JSROOT.Create("TAttText", obj); + JSROOT.extend(obj, { _fChopt: "", fFunctionName: "", fGridLength: 0, + fLabelColor: 1, fLabelFont: 42, fLabelOffset: 0.005, fLabelSize: 0.035, + fName: "", fNdiv: 12, fTickSize: 0.02, fTimeFormat: "", + fTitle: "", fTitleOffset: 1, fTitleSize: 0.035, + fWmax: 100, fWmin: 0 }); + break; + case 'TAttPad': + JSROOT.extend(obj, { fLeftMargin: 0.1, fRightMargin: 0.1, fBottomMargin: 0.1, fTopMargin: 0.1, + fXfile: 2, fYfile: 2, fAfile: 1, fXstat: 0.99, fYstat: 0.99, fAstat: 2, + fFrameFillColor: 0, fFrameLineColor: 1, fFrameFillStyle: 1001, + fFrameLineStyle: 1, fFrameLineWidth: 1, fFrameBorderSize: 1, + fFrameBorderMode: 0 }); + break; + case 'TPad': + JSROOT.Create("TObject", obj); + JSROOT.Create("TAttLine", obj); + JSROOT.Create("TAttFill", obj); + JSROOT.Create("TAttPad", obj); + JSROOT.extend(obj, { fX1: 0, fY1: 0, fX2: 1, fY2: 1, fXtoAbsPixelk: 1, fXtoPixelk: 1, + fXtoPixel: 1, fYtoAbsPixelk: 1, fYtoPixelk: 1, fYtoPixel: 1, + fUtoAbsPixelk: 1, fUtoPixelk: 1, fUtoPixel: 1, fVtoAbsPixelk: 1, + fVtoPixelk: 1, fVtoPixel: 1, fAbsPixeltoXk: 1, fPixeltoXk: 1, + fPixeltoX: 1, fAbsPixeltoYk: 1, fPixeltoYk: 1, fPixeltoY: 1, + fXlowNDC: 0, fYlowNDC: 0, fXUpNDC: 0, fYUpNDC: 0, fWNDC: 1, fHNDC: 1, + fAbsXlowNDC: 0, fAbsYlowNDC: 0, fAbsWNDC: 1, fAbsHNDC: 1, + fUxmin: 0, fUymin: 0, fUxmax: 0, fUymax: 0, fTheta: 30, fPhi: 30, fAspectRatio: 0, + fNumber: 0, fTickx: 0, fTicky: 0, fLogx: 0, fLogy: 0, fLogz: 0, + fPadPaint: 0, fCrosshair: 0, fCrosshairPos: 0, fBorderSize: 2, + fBorderMode: 0, fModified: false, fGridx: false, fGridy: false, + fAbsCoord: false, fEditable: true, fFixedAspectRatio: false, + fPrimitives: JSROOT.Create("TList"), fExecs: null, + fName: "pad", fTitle: "canvas" }); + break; + case 'TAttCanvas': + JSROOT.extend(obj, { fXBetween: 2, fYBetween: 2, fTitleFromTop: 1.2, + fXdate: 0.2, fYdate: 0.3, fAdate: 1 }); + break; + case 'TCanvas': + JSROOT.Create("TPad", obj); + JSROOT.extend(obj, { fDoubleBuffer: 0, fRetained: true, fXsizeUser: 0, + fYsizeUser: 0, fXsizeReal: 20, fYsizeReal: 10, + fWindowTopX: 0, fWindowTopY: 0, fWindowWidth: 0, fWindowHeight: 0, + fCw: 800, fCh : 500, fCatt: JSROOT.Create("TAttCanvas"), + kMoveOpaque: true, kResizeOpaque: true, fHighLightColor: 5, + fBatch: true, kShowEventStatus: false, kAutoExec: true, kMenuBar: true }); + break; + case 'TGeoVolume': + JSROOT.Create("TNamed", obj); + JSROOT.Create("TAttLine", obj); + JSROOT.Create("TAttFill", obj); + JSROOT.extend(obj, { fGeoAtt:0, fFinder: null, fMedium: null, fNodes: null, fNtotal: 0, fNumber: 0, fRefCount: 0, fShape: null, fVoxels: null }); + break; + case 'TGeoNode': + JSROOT.Create("TNamed", obj); + JSROOT.extend(obj, { fGeoAtt:0, fMother: null, fNovlp: 0, fNumber: 0, fOverlaps: null, fVolume: null }); + break; + case 'TGeoNodeMatrix': + JSROOT.Create("TGeoNode", obj); + JSROOT.extend(obj, { fMatrix: null }); + break; + } + + obj._typename = typename; + this.addMethods(obj); + return obj; + } + + // obsolete functions, can be removed by next JSROOT release + JSROOT.CreateTList = function() { return JSROOT.Create("TList"); } + JSROOT.CreateTAxis = function() { return JSROOT.Create("TAxis"); } + + JSROOT.CreateTH1 = function(nbinsx) { + + var histo = JSROOT.extend(JSROOT.Create("TH1I"), + { fName: "dummy_histo_" + this.id_counter++, fTitle: "dummytitle" }); + + if (nbinsx!==undefined) { + histo.fNcells = nbinsx+2; + for (var i=0;i0) { + graph.fMaxSize = graph.fNpoints = npoints; + + var usex = (typeof xpts == 'object') && (xpts.length === npoints); + var usey = (typeof ypts == 'object') && (ypts.length === npoints); + + for (var i=0;i= 0) + _func = _func.replace(this.formulas[i].fName, this.formulas[i].fTitle); + _func = _func.replace(/\b(abs)\b/g, 'TMath::Abs'); + _func = _func.replace('TMath::Exp(', 'Math.exp('); + _func = _func.replace('TMath::Abs(', 'Math.abs('); + if (typeof JSROOT.Math == 'object') { + this._math = JSROOT.Math; + _func = _func.replace('TMath::Prob(', 'this._math.Prob('); + _func = _func.replace('TMath::Gaus(', 'this._math.Gaus('); + _func = _func.replace('gaus(', 'this._math.gaus(this, x, '); + _func = _func.replace('gausn(', 'this._math.gausn(this, x, '); + _func = _func.replace('expo(', 'this._math.expo(this, x, '); + _func = _func.replace('landau(', 'this._math.landau(this, x, '); + _func = _func.replace('landaun(', 'this._math.landaun(this, x, '); + } + _func = _func.replace('pi', 'Math.PI'); + for (var i=0;i=yp) || (y[j]=yp)) { + if (x[i]+(yp-y[i])/(y[j]-y[i])*(x[j]-x[i])= this.fNcells) bin = this.fNcells - 1; + if (bin < 0) bin = 0; + if (bin < this.fSumw2.length) + return Math.sqrt(this.fSumw2[bin]); + return Math.sqrt(Math.abs(this.fArray[bin])); + }; + m.setBinContent = function(bin, content) { + // Set bin content - only trival case, without expansion + this.fEntries++; + this.fTsumw = 0; + if ((bin>=0) && (bin= this.fNcells) return 0; + if (this.fBinEntries[bin] < 1e-300) return 0; + if (!this.fArray) return 0; + return this.fArray[bin]/this.fBinEntries[bin]; + }; + m.getBinEffectiveEntries = function(bin) { + if (bin < 0 || bin >= this.fNcells) return 0; + var sumOfWeights = this.fBinEntries[bin]; + if ( this.fBinSumw2 == null || this.fBinSumw2.length != this.fNcells) { + // this can happen when reading an old file + return sumOfWeights; + } + var sumOfWeightsSquare = this.fSumw2[bin]; + return ( sumOfWeightsSquare > 0 ? sumOfWeights * sumOfWeights / sumOfWeightsSquare : 0 ); + }; + m.getBinError = function(bin) { + if (bin < 0 || bin >= this.fNcells) return 0; + var cont = this.fArray[bin], // sum of bin w *y + sum = this.fBinEntries[bin], // sum of bin weights + err2 = this.fSumw2[bin], // sum of bin w * y^2 + neff = this.getBinEffectiveEntries(bin); // (sum of w)^2 / (sum of w^2) + if (sum < 1e-300) return 0; // for empty bins + var EErrorType = { kERRORMEAN : 0, kERRORSPREAD : 1, kERRORSPREADI : 2, kERRORSPREADG : 3 }; + // case the values y are gaussian distributed y +/- sigma and w = 1/sigma^2 + if (this.fErrorMode === EErrorType.kERRORSPREADG) + return 1.0/Math.sqrt(sum); + // compute variance in y (eprim2) and standard deviation in y (eprim) + var contsum = cont/sum; + var eprim2 = Math.abs(err2/sum - contsum*contsum); + var eprim = Math.sqrt(eprim2); + if (this.fErrorMode === EErrorType.kERRORSPREADI) { + if (eprim != 0) return eprim/Math.sqrt(neff); + // in case content y is an integer (so each my has an error +/- 1/sqrt(12) + // when the std(y) is zero + return 1.0/Math.sqrt(12*neff); + } + // if approximate compute the sums (of w, wy and wy2) using all the bins + // when the variance in y is zero + // case option "S" return standard deviation in y + if (this.fErrorMode === EErrorType.kERRORSPREAD) return eprim; + // default case : fErrorMode = kERRORMEAN + // return standard error on the mean of y + return (eprim/Math.sqrt(neff)); + }; + } + + if (typename == "TAxis") { + m.GetBinLowEdge = function(bin) { + if (this.fNbins <= 0) return 0; + if ((this.fXbins.length > 0) && (bin > 0) && (bin <= this.fNbins)) return this.fXbins[bin-1]; + return this.fXmin + (bin-1) * (this.fXmax - this.fXmin) / this.fNbins; + } + } + + JSROOT.methodsCache[typename] = m; + return m; + }; + + JSROOT.addMethods = function(obj) { + this.extend(obj, JSROOT.getMethods(obj._typename, obj)); + }; + + JSROOT.lastFFormat = ""; + + JSROOT.FFormat = function(value, fmt) { + // method used to convert numeric value to string according specified format + // format can be like 5.4g or 4.2e or 6.4f + // function saves actual format in JSROOT.lastFFormat variable + if (!fmt) fmt = "6.4g"; + + JSROOT.lastFFormat = ""; + + fmt = fmt.trim(); + var len = fmt.length; + if (len<2) return value.toFixed(4); + var last = fmt.charAt(len-1); + fmt = fmt.slice(0,len-1); + var isexp = null; + var prec = fmt.indexOf("."); + if (prec<0) prec = 4; else prec = Number(fmt.slice(prec+1)); + if (isNaN(prec) || (prec<0) || (prec==null)) prec = 4; + + var significance = false; + if ((last=='e') || (last=='E')) { isexp = true; } else + if (last=='Q') { isexp = true; significance = true; } else + if ((last=='f') || (last=='F')) { isexp = false; } else + if (last=='W') { isexp = false; significance = true; } else + if ((last=='g') || (last=='G')) { + var se = JSROOT.FFormat(value, fmt+'Q'); + var _fmt = JSROOT.lastFFormat; + var sg = JSROOT.FFormat(value, fmt+'W'); + + if (se.length < sg.length) { + JSROOT.lastFFormat = _fmt; + return se; + } + return sg; + } else { + isexp = false; + prec = 4; + } + + if (isexp) { + // for exponential representation only one significant digit befor point + if (significance) prec--; + if (prec<0) prec = 0; + + JSROOT.lastFFormat = '5.'+prec+'e'; + + return value.toExponential(prec); + } + + var sg = value.toFixed(prec); + + if (significance) { + + // when using fixed representation, one could get 0.0 + if ((value!=0) && (Number(sg)==0.) && (prec>0)) { + prec = 20; sg = value.toFixed(prec); + } + + var l = 0; + while ((ll) diff--; + + if (diff != 0) { + prec-=diff; + if (prec<0) prec = 0; else if (prec>20) prec = 20; + sg = value.toFixed(prec); + } + } + + JSROOT.lastFFormat = '5.'+prec+'f'; + + return sg; + } + + JSROOT.log10 = function(n) { + return Math.log(n) / Math.log(10); + } + + // dummy function, will be redefined when JSRootPainter is loaded + JSROOT.progress = function(msg) { + if ((msg !== undefined) && (typeof msg=="string")) JSROOT.console(msg); + } + + JSROOT.Initialize = function() { + + if (JSROOT.source_fullpath.length === 0) return this; + + function window_on_load(func) { + if (func!=null) { + if (document.attachEvent ? document.readyState === 'complete' : document.readyState !== 'loading') + func(); + else + window.onload = func; + } + return JSROOT; + } + + var src = JSROOT.source_fullpath; + + if (JSROOT.GetUrlOption('gui', src) !== null) + return window_on_load( function() { JSROOT.BuildSimpleGUI(); } ); + + if ( typeof define === "function" && define.amd ) + return window_on_load( function() { JSROOT.BuildSimpleGUI('check_existing_elements'); } ); + + var prereq = ""; + if (JSROOT.GetUrlOption('io', src)!=null) prereq += "io;"; + if (JSROOT.GetUrlOption('2d', src)!=null) prereq += "2d;"; + if (JSROOT.GetUrlOption('jq2d', src)!=null) prereq += "jq2d;"; + if (JSROOT.GetUrlOption('more2d', src)!=null) prereq += "more2d;"; + if (JSROOT.GetUrlOption('geo', src)!=null) prereq += "geo;"; + if (JSROOT.GetUrlOption('3d', src)!=null) prereq += "3d;"; + if (JSROOT.GetUrlOption('math', src)!=null) prereq += "math;"; + if (JSROOT.GetUrlOption('mathjax', src)!=null) prereq += "mathjax;"; + var user = JSROOT.GetUrlOption('load', src); + if ((user!=null) && (user.length>0)) prereq += "load:" + user; + var onload = JSROOT.GetUrlOption('onload', src); + var bower = JSROOT.GetUrlOption('bower', src); + if (bower!==null) { + if (bower.length>0) JSROOT.bower_dir = bower; else + if (JSROOT.source_dir.indexOf("jsroot/") == JSROOT.source_dir.length - 7) + JSROOT.bower_dir = JSROOT.source_dir.substr(0, JSROOT.source_dir.length - 7); + if (JSROOT.bower_dir.length > 0) console.log("Set JSROOT.bower_dir to " + JSROOT.bower_dir); + } + + if ((prereq.length>0) || (onload!=null)) + window_on_load(function() { + if (prereq.length>0) JSROOT.AssertPrerequisites(prereq, onload); else + if (onload!=null) { + onload = JSROOT.findFunction(onload); + if (typeof onload == 'function') onload(); + } + }); + + return this; + } + + return JSROOT.Initialize(); + +})); + +/// JSRootCore.js ends + diff --git a/visualisations/JsRoot460/scripts/JSRootCore.min.js b/visualisations/JsRoot460/scripts/JSRootCore.min.js new file mode 100644 index 0000000..d7fc53b --- /dev/null +++ b/visualisations/JsRoot460/scripts/JSRootCore.min.js @@ -0,0 +1 @@ +(function(b){if(typeof define==="function"&&define.amd){var e=b({});var c=e.source_dir+"scripts/",f=e.source_min?".min":"";var g={d3:c+"d3.v3.min",jquery:c+"jquery.min","jquery-ui":c+"jquery-ui.min","jqueryui-mousewheel":c+"jquery.mousewheel"+f,"jqueryui-touch-punch":c+"touch-punch.min",rawinflate:c+"rawinflate"+f,MathJax:"https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_SVG&delayStartupUntil=configured",saveSvgAsPng:c+"saveSvgAsPng"+f,"dat.gui":c+"dat.gui.min",threejs:c+"three",threejs_all:c+"three.extra"+f,JSRootCore:c+"JSRootCore"+f,JSRootMath:c+"JSRootMath"+f,JSRootInterface:c+"JSRootInterface"+f,JSRootIOEvolution:c+"JSRootIOEvolution"+f,JSRootPainter:c+"JSRootPainter"+f,"JSRootPainter.more":c+"JSRootPainter.more"+f,"JSRootPainter.jquery":c+"JSRootPainter.jquery"+f,JSRoot3DPainter:c+"JSRoot3DPainter"+f,ThreeCSG:c+"ThreeCSG"+f,JSRootGeoBase:c+"JSRootGeoBase"+f,JSRootGeoPainter:c+"JSRootGeoPainter"+f};var a;if((requirejs.s!==undefined)&&(requirejs.s.contexts!==undefined)&&((requirejs.s.contexts._!==undefined)&&requirejs.s.contexts._.config!==undefined)){a=requirejs.s.contexts._.config.paths}else{console.warn("Require.js paths changed - please contact JSROOT developers")}for(var d in g){if(requirejs.defined(d)||(a&&(d in a))){delete g[d]}}requirejs.config({paths:g,shim:{"jqueryui-mousewheel":{deps:["jquery-ui"]},"jqueryui-touch-punch":{deps:["jquery-ui"]},threejs_all:{deps:["threejs"]},ThreeCSG:{deps:["threejs"]},MathJax:{exports:"MathJax",init:function(){MathJax.Hub.Config({TeX:{extensions:["color.js"]}});MathJax.Hub.Register.StartupHook("SVG Jax Ready",function(){var h=MathJax.OutputJax.SVG.FONTDATA.VARIANT;h.normal.fonts.unshift("MathJax_SansSerif");h.bold.fonts.unshift("MathJax_SansSerif-bold");h.italic.fonts.unshift("MathJax_SansSerif");h["-tex-mathit"].fonts.unshift("MathJax_SansSerif")});MathJax.Hub.Startup.onload();return MathJax}}}});define(e);if(!require.specified("JSRootCore")){define("JSRootCore",[],e)}if(!require.specified("jsroot")){define("jsroot",[],e)}}else{if(typeof JSROOT!="undefined"){throw new Error("JSROOT is already defined","JSRootCore.js")}JSROOT={};b(JSROOT)}}(function(b){b.version="4.6.0 22/08/2016";b.source_dir="";b.source_min=false;b.source_fullpath="";b.bower_dir="";b.id_counter=0;b.touches=false;b.browser={isOpera:false,isFirefox:true,isSafari:false,isChrome:false,isIE:false};if((typeof document!=="undefined")&&(typeof window!=="undefined")){var a=document.getElementsByTagName("script");for(var e=0;e=0;b.source_fullpath=c;if((console!==undefined)&&(typeof console.log=="function")){console.log("Set JSROOT.source_dir to "+b.source_dir+", "+b.version)}break}b.touches=("ontouchend" in document);b.browser.isOpera=!!window.opera||navigator.userAgent.indexOf(" OPR/")>=0;b.browser.isFirefox=typeof InstallTrigger!=="undefined";b.browser.isSafari=Object.prototype.toString.call(window.HTMLElement).indexOf("Constructor")>0;b.browser.isChrome=!!window.chrome&&!b.browser.isOpera;b.browser.isIE=false||!!document.documentMode}b.browser.isWebKit=b.browser.isChrome||b.browser.isSafari;b.gStyle={Tooltip:1,ContextMenu:true,Zooming:true,MoveResize:true,DragAndDrop:true,ToolBar:true,OptimizeDraw:1,AutoStat:true,OptStat:1111,OptFit:0,FrameNDC:{fX1NDC:0.07,fY1NDC:0.12,fX2NDC:0.95,fY2NDC:0.88},StatNDC:{fX1NDC:0.78,fY1NDC:0.75,fX2NDC:0.98,fY2NDC:0.91},StatText:{fTextAngle:0,fTextSize:9,fTextAlign:12,fTextColor:1,fTextFont:42},StatFill:{fFillColor:0,fFillStyle:1001},TimeOffset:788918400000,StatFormat:"6.4g",FitFormat:"5.4g",Palette:57,MathJax:0,ProgressBox:true,Embed3DinSVG:2,NoWebGL:false,EndErrorSize:2,GeoGradPerSegm:6,GeoCompressComp:true};b.BIT=function(f){return 1<<(f)};b.TH1StatusBits={kNoStats:b.BIT(9),kUserContour:b.BIT(10),kCanRebin:b.BIT(11),kLogX:b.BIT(15),kIsZoomed:b.BIT(16),kNoTitle:b.BIT(17),kIsAverage:b.BIT(18)};b.EAxisBits={kTickPlus:b.BIT(9),kTickMinus:b.BIT(10),kAxisRange:b.BIT(11),kCenterTitle:b.BIT(12),kCenterLabels:b.BIT(14),kRotateTitle:b.BIT(15),kPalette:b.BIT(16),kNoExponent:b.BIT(17),kLabelsHori:b.BIT(18),kLabelsVert:b.BIT(19),kLabelsDown:b.BIT(20),kLabelsUp:b.BIT(21),kIsInteger:b.BIT(22),kMoreLogLabels:b.BIT(23),kDecimals:b.BIT(11)};b.console=function(f,g){if((g!=null)&&(typeof g=="string")&&((typeof document.getElementById(g))!="undefined")){document.getElementById(g).innerHTML=f}else{if((typeof console!="undefined")&&(typeof console.log=="function")){console.log(f)}}};b.JSONR_unref_str=function(h,f){var g=parseInt(h.substr(5));return(!isNaN(g)&&(g>=0)&&(g5)&&(h.indexOf("$ref:")===0)){m[j]=this.JSONR_unref_str(h,f)}}else{if((typeof h==="object")&&(h!==null)){this.JSONR_unref_obj(h,f)}}}return}if(f.indexOf(m)>=0){return}f.push(m);if("_typename" in m){this.addMethods(m)}var n=Object.keys(m);for(var g=0;g5)&&(h.indexOf("$ref:")===0)){m[j]=this.JSONR_unref_str(h,f)}}else{if((typeof h==="object")&&(h!==null)){this.JSONR_unref_obj(h,f)}}}return m};b.JSONR_unref=function(f){if((typeof f==="object")&&(f!==null)){this.JSONR_unref_obj(f,[])}return f};b.debug=0;b.extend=function(h,g){if((g===null)||(typeof g!=="object")){return g}if((h===null)||(typeof h!=="object")){h={}}for(var f in g){h[f]=g[f]}return h};b.clone=function(m,l,g){if(m===null){return null}if(!l){l={obj:[],clones:[],nofunc:g}}else{var h=l.obj.indexOf(m);if(h>=0){return l.clones[h]}}var j=Object.prototype.toString.apply(m);if(j==="[object Array]"){var n=[];l.obj.push(m);l.clones.push(n);for(var h=0;h0){if(f==g){return""}i=f.indexOf("&");if(i<0){i=f.length}if(f.indexOf(g)==0){if(f.charAt(g.length)=="&"){return""}if(f.charAt(g.length)=="="){return f.slice(g.length+1,i).replace(/%27/g,"'").replace(/%22/g,'"').replace(/%20/g," ").replace(/%3C/g,"<").replace(/%3E/g,">").replace(/%5B/g,"[").replace(/%5D/g,"]")}}f=f.slice(i+1)}return h};b.ParseAsArray=function(k){var h=[];if(typeof k!="string"){return h}k=k.trim();if(k==""){return h}if((k.length<2)||(k[0]!="[")||(k[k.length-1]!="]")){h.push(k);return h}var f=k.substr(1,k.length-2).split(",");for(var g=0;g1)&&(j[0]==j[j.length-1])&&((j[0]=='"')||(j[0]=="'"))){j=j.substr(1,j.length-2)}h.push(j)}return h};b.GetUrlOptionAsArray=function(i,g){var h=[];while(i.length>0){var j=i.indexOf(";");var f=j>0?i.substr(0,j):i;if(j>0){i=i.substr(j+1)}else{i=""}var k=this.GetUrlOption(f,g,null);h=h.concat(b.ParseAsArray(k))}return h};b.findFunction=function(f){if(typeof f==="function"){return f}if(typeof window[f]=="function"){return window[f]}if((typeof f!=="string")||(f.indexOf(".")<0)){return null}var h=f.split("."),g=window;for(var i=0;i0)){return b.loadScript(x,j,i)}b.CallBack(j)}if((x==null)||(x.length==0)){return m()}var u=x;var q=u.indexOf(";");if(q>0){u=u.substr(0,q);x=x.slice(q+1)}else{x=""}var w=false,r=false;if(u.indexOf("$$$")===0){w=true;u=u.slice(3);if((u.indexOf("style/")==0)&&b.source_min&&(u.lastIndexOf(".css")==u.length-3)&&(u.indexOf(".min.css")<0)){u=u.slice(0,u.length-4)+".min.css"}}else{if(u.indexOf("###")===0){r=true;u=u.slice(3)}}var o=u.indexOf(".typeface.json");if(o>0){var g="threejs_font_"+u.slice(u.lastIndexOf("/")+1,o);if(typeof b[g]!=="undefined"){return m()}if((typeof THREE==="undefined")||(typeof THREE.FontLoader==="undefined")){console.log("fail to load",u,"no (proper) three.js found");return m()}b.progress("loading "+u+" ...");var p=new THREE.FontLoader();p.load(u,function(n){b[g]=n;m()});return}var s=u.indexOf(".css")>0;if(s){var l=document.getElementsByTagName("link");for(var t=0;t=0){return m()}}}else{var h=document.getElementsByTagName("script");for(var t=0;t=0)&&(k.indexOf("load=")<0)){return m()}}}if(w&&(b.source_dir!=null)){u=b.source_dir+u}else{if(r&&(b.bower_dir.length>0)){u=b.bower_dir+u}}var f=null;if(i){document.getElementById(i).innerHTML="loading "+u+" ..."}else{b.progress("loading "+u+" ...")}if(s){f=document.createElement("link");f.setAttribute("rel","stylesheet");f.setAttribute("type","text/css");f.setAttribute("href",u)}else{f=document.createElement("script");f.setAttribute("type","text/javascript");f.setAttribute("src",u)}if(f.readyState){f.onreadystatechange=function(){if(f.readyState=="loaded"||f.readyState=="complete"){f.onreadystatechange=null;m()}}}else{f.onload=function(){f.onload=null;m()}}document.getElementsByTagName("head")[0].appendChild(f)};b.AssertPrerequisites=function(o,v,m){var j=b;if(j.doing_assert===undefined){j.doing_assert=[]}if(j.ready_modules===undefined){j.ready_modules=[]}if((typeof o!=="string")||(o=="")){return j.CallBack(v)}if(o==="__next__"){if(j.doing_assert.length==0){return}var t=j.doing_assert[0];if(t.running){return}o=t._kind;v=t._callback;m=t._debug}else{j.doing_assert.push({_kind:o,_callback:v,_debug:m});if(j.doing_assert.length>1){return}}j.doing_assert[0].running=true;if(o.charAt(o.length-1)!=";"){o+=";"}var h=j.source_min?".min":"",g=false,f=(j.bower_dir.length>0),q="",l="",k=[];if(o.indexOf("io;")>=0){q+="$$$scripts/rawinflate"+h+".js;$$$scripts/JSRootIOEvolution"+h+".js;";k.push("JSRootIOEvolution")}if(o.indexOf("2d;")>=0){if(j._test_d3_===undefined){if(typeof d3!="undefined"){j.console("Reuse existing d3.js "+d3.version+", required 3.5.9",m);j._test_d3_=1}else{q+=f?"###d3/d3.min.js;":"$$$scripts/d3.v3.min.js;";j._test_d3_=2}}k.push("JSRootPainter");q+="$$$scripts/JSRootPainter"+h+".js;";l+="$$$style/JSRootPainter"+h+".css;"}if(o.indexOf("savepng;")>=0){k.push("saveSvgAsPng");q+="$$$scripts/saveSvgAsPng"+h+".js;"}if(o.indexOf("jq;")>=0){g=true}if(o.indexOf("math;")>=0){q+="$$$scripts/JSRootMath"+h+".js;";k.push("JSRootMath")}if(o.indexOf("more2d;")>=0){q+="$$$scripts/JSRootPainter.more"+h+".js;";k.push("JSRootPainter.more")}if(o.indexOf("jq2d;")>=0){q+="$$$scripts/JSRootPainter.jquery"+h+".js;";k.push("JSRootPainter.jquery");g=true}if((o.indexOf("3d;")>=0)||(o.indexOf("geom;")>=0)){if(f){q+="###threejs/build/three.min.js;###threejs/examples/js/renderers/Projector.js;###threejs/examples/js/renderers/CanvasRenderer.js;###threejs/examples/js/controls/OrbitControls.js;###threejs/examples/js/controls/TransformControls.js;###threejs/examples/js/shaders/CopyShader.js;###threejs/examples/js/postprocessing/EffectComposer.js;###threejs/examples/js/postprocessing/MaskPass.js;###threejs/examples/js/postprocessing/RenderPass.js;###threejs/examples/js/postprocessing/ShaderPass.js;###threejs/examples/js/shaders/SSAOShader.js;";l+="###threejs/examples/fonts/helvetiker_regular.typeface.json;"}else{q+="$$$scripts/three.js;$$$scripts/three.extra"+h+".js;"}k.push("threejs_all");q+="$$$scripts/JSRoot3DPainter"+h+".js;";k.push("JSRoot3DPainter")}if(o.indexOf("geom;")>=0){q+="$$$scripts/ThreeCSG"+h+".js;$$$scripts/JSRootGeoBase"+h+".js;$$$scripts/JSRootGeoPainter"+h+".js;$$$scripts/dat.gui.min.js;";l+="$$$style/JSRootGeoPainter"+h+".css;";k.push("ThreeCSG","JSRootGeoBase","JSRootGeoPainter","dat.gui")}if(o.indexOf("mathjax;")>=0){if(typeof MathJax=="undefined"){q+=(f?"###MathJax/MathJax.js":"https://cdn.mathjax.org/mathjax/latest/MathJax.js")+"?config=TeX-AMS-MML_SVG,"+j.source_dir+"scripts/mathjax_config.js;"}if(j.gStyle.MathJax==0){j.gStyle.MathJax=1}k.push("MathJax")}if(o.indexOf("simple;")>=0){g=true;q+="$$$scripts/JSRootInterface"+h+".js;";l+="$$$style/JSRootInterface"+h+".css;";k.push("JSRootInterface")}if(g&&!j.load_jquery){var p=(typeof jQuery!="undefined"),s="";if(p){j.console("Reuse existing jQuery "+jQuery.fn.jquery+", required 2.1.4",m)}else{s+=(f?"###jquery/dist":"$$$scripts")+"/jquery.min.js;"}if(p&&typeof $.ui!="undefined"){j.console("Reuse existing jQuery-ui "+$.ui.version+", required 1.11.4",m)}else{s+=(f?"###jquery-ui":"$$$scripts")+"/jquery-ui.min.js;";l+="$$$style/jquery-ui"+h+".css;"}if(j.touches){s+=f?"###jqueryui-touch-punch/jquery.ui.touch-punch.min.js;":"$$$scripts/touch-punch.min.js;";k.push("jqueryui-touch-punch")}k.splice(0,0,"jquery","jquery-ui","jqueryui-mousewheel");q=s+q;j.load_jquery=true}var r=o.indexOf("user:");if(r<0){r=o.indexOf("load:")}if(r>=0){l+=o.slice(r+5)}function u(){var w=j.doing_assert.shift();for(var x=0;x=0;--i){if(j.ready_modules.indexOf(k[i])>=0){k.splice(i,1)}}if(k.length===0){q=""}j.doing_assert[0].modules=k;if((k.length>0)&&(typeof define==="function")&&define.amd){j.console("loading "+JSON.stringify(k)+" with require.js",m);require(k,function(){j.loadScript(l,u,m)})}else{j.loadScript(q+l,u,m)}};b.OpenFile=function(f,g){b.AssertPrerequisites("io",function(){new b.TFile(f,g)})};b.draw=function(h,g,f){b.AssertPrerequisites("2d",function(){b.draw(h,g,f)})};b.redraw=function(h,g,f){b.AssertPrerequisites("2d",function(){b.redraw(h,g,f)})};b.BuildSimpleGUI=function(j,f){if(typeof j=="function"){f=j;j=null}var i=null;var h=b.GetUrlOption("nobrowser")!=null;var g="io;2d;";if(document.getElementById("simpleGUI")){i="simpleGUI";if((b.GetUrlOption("json")!=null)&&(b.GetUrlOption("file")==null)&&(b.GetUrlOption("files")==null)){g="2d;"}}else{if(document.getElementById("onlineGUI")){i="onlineGUI";g="2d;"}else{if(document.getElementById("drawGUI")){i="drawGUI";g="2d;";h=true}}}if(j=="check_existing_elements"){j=null;if(i==null){return}}if(!h){g+="jq2d;simple;"}if(j==null){j=b.GetUrlOption("autoload")}if(j==null){j=b.GetUrlOption("load")}if(j!=null){g+="load:"+j+";"}b.AssertPrerequisites(g,function(){b.CallBack(b.findFunction(h?"JSROOT.BuildNobrowserGUI":"BuildSimpleGUI"));b.CallBack(f)},i)};b.Create=function(f,h){var g=h;if(g==null){g={_typename:f}}switch(f){case"TObject":b.extend(g,{fUniqueID:0,fBits:50331656});break;case"TNamed":b.extend(g,{fUniqueID:0,fBits:50331656,fName:"",fTitle:""});break;case"TList":case"THashList":b.extend(g,{name:f,arr:[],opt:[]});break;case"TAttAxis":b.extend(g,{fNdivisions:510,fAxisColor:1,fLabelColor:1,fLabelFont:42,fLabelOffset:0.005,fLabelSize:0.035,fTickLength:0.03,fTitleOffset:1,fTitleSize:0.035,fTitleColor:1,fTitleFont:42});break;case"TAxis":b.Create("TNamed",g);b.Create("TAttAxis",g);b.extend(g,{fNbins:0,fXmin:0,fXmax:0,fXbins:[],fFirst:0,fLast:0,fBits2:0,fTimeDisplay:false,fTimeFormat:"",fLabels:null});break;case"TAttLine":b.extend(g,{fLineColor:1,fLineStyle:1,fLineWidth:1});break;case"TAttFill":b.extend(g,{fFillColor:0,fFillStyle:0});break;case"TAttMarker":b.extend(g,{fMarkerColor:1,fMarkerStyle:1,fMarkerSize:1});break;case"TLine":b.Create("TObject",g);b.Create("TAttLine",g);b.extend(g,{fX1:0,fX2:1,fY1:0,fY2:1});break;case"TBox":b.Create("TObject",g);b.Create("TAttLine",g);b.Create("TAttFill",g);b.extend(g,{fX1:0,fX2:1,fY1:0,fY2:1});break;case"TPave":b.Create("TBox",g);b.extend(g,{fX1NDC:0,fY1NDC:0,fX2NDC:1,fY2NDC:1,fBorderSize:0,fInit:1,fShadowColor:1,fCornerRadius:0,fOption:"blNDC",fName:"title"});break;case"TAttText":b.extend(g,{fTextAngle:0,fTextSize:0,fTextAlign:22,fTextColor:1,fTextFont:42});break;case"TPaveText":b.Create("TPave",g);b.Create("TAttText",g);b.extend(g,{fLabel:"",fLongest:27,fMargin:0.05,fLines:b.Create("TList")});break;case"TPaveStats":b.Create("TPaveText",g);b.extend(g,{fOptFit:0,fOptStat:0,fFitFormat:"",fStatFormat:"",fParent:null});break;case"TObjString":b.Create("TObject",g);b.extend(g,{fString:""});break;case"TH1":b.Create("TNamed",g);b.Create("TAttLine",g);b.Create("TAttFill",g);b.Create("TAttMarker",g);b.extend(g,{fNcells:0,fXaxis:b.Create("TAxis"),fYaxis:b.Create("TAxis"),fZaxis:b.Create("TAxis"),fBarOffset:0,fBarWidth:1000,fEntries:0,fTsumw:0,fTsumw2:0,fTsumwx:0,fTsumwx2:0,fMaximum:-1111,fMinimum:-1111,fNormFactor:0,fContour:[],fSumw2:[],fOption:"",fFunctions:b.Create("TList"),fBufferSize:0,fBuffer:[],fBinStatErrOpt:0});break;case"TH1I":case"TH1F":case"TH1D":case"TH1S":case"TH1C":b.Create("TH1",g);g.fArray=[];break;case"TH2":b.Create("TH1",g);b.extend(g,{fScalefactor:1,fTsumwy:0,fTsumwy2:0,fTsumwxy:0});break;case"TH2I":case"TH2F":case"TH2D":case"TH2S":case"TH2C":b.Create("TH2",g);g.fArray=[];break;case"TGraph":b.Create("TNamed",g);b.Create("TAttLine",g);b.Create("TAttFill",g);b.Create("TAttMarker",g);b.extend(g,{fFunctions:b.Create("TList"),fHistogram:null,fMaxSize:0,fMaximum:-1111,fMinimum:-1111,fNpoints:0,fX:[],fY:[]});break;case"TMultiGraph":b.Create("TNamed",g);b.extend(g,{fFunctions:b.Create("TList"),fGraphs:b.Create("TList"),fHistogram:null,fMaximum:-1111,fMinimum:-1111});break;case"TGaxis":b.Create("TLine",g);b.Create("TAttText",g);b.extend(g,{_fChopt:"",fFunctionName:"",fGridLength:0,fLabelColor:1,fLabelFont:42,fLabelOffset:0.005,fLabelSize:0.035,fName:"",fNdiv:12,fTickSize:0.02,fTimeFormat:"",fTitle:"",fTitleOffset:1,fTitleSize:0.035,fWmax:100,fWmin:0});break;case"TAttPad":b.extend(g,{fLeftMargin:0.1,fRightMargin:0.1,fBottomMargin:0.1,fTopMargin:0.1,fXfile:2,fYfile:2,fAfile:1,fXstat:0.99,fYstat:0.99,fAstat:2,fFrameFillColor:0,fFrameLineColor:1,fFrameFillStyle:1001,fFrameLineStyle:1,fFrameLineWidth:1,fFrameBorderSize:1,fFrameBorderMode:0});break;case"TPad":b.Create("TObject",g);b.Create("TAttLine",g);b.Create("TAttFill",g);b.Create("TAttPad",g);b.extend(g,{fX1:0,fY1:0,fX2:1,fY2:1,fXtoAbsPixelk:1,fXtoPixelk:1,fXtoPixel:1,fYtoAbsPixelk:1,fYtoPixelk:1,fYtoPixel:1,fUtoAbsPixelk:1,fUtoPixelk:1,fUtoPixel:1,fVtoAbsPixelk:1,fVtoPixelk:1,fVtoPixel:1,fAbsPixeltoXk:1,fPixeltoXk:1,fPixeltoX:1,fAbsPixeltoYk:1,fPixeltoYk:1,fPixeltoY:1,fXlowNDC:0,fYlowNDC:0,fXUpNDC:0,fYUpNDC:0,fWNDC:1,fHNDC:1,fAbsXlowNDC:0,fAbsYlowNDC:0,fAbsWNDC:1,fAbsHNDC:1,fUxmin:0,fUymin:0,fUxmax:0,fUymax:0,fTheta:30,fPhi:30,fAspectRatio:0,fNumber:0,fTickx:0,fTicky:0,fLogx:0,fLogy:0,fLogz:0,fPadPaint:0,fCrosshair:0,fCrosshairPos:0,fBorderSize:2,fBorderMode:0,fModified:false,fGridx:false,fGridy:false,fAbsCoord:false,fEditable:true,fFixedAspectRatio:false,fPrimitives:b.Create("TList"),fExecs:null,fName:"pad",fTitle:"canvas"});break;case"TAttCanvas":b.extend(g,{fXBetween:2,fYBetween:2,fTitleFromTop:1.2,fXdate:0.2,fYdate:0.3,fAdate:1});break;case"TCanvas":b.Create("TPad",g);b.extend(g,{fDoubleBuffer:0,fRetained:true,fXsizeUser:0,fYsizeUser:0,fXsizeReal:20,fYsizeReal:10,fWindowTopX:0,fWindowTopY:0,fWindowWidth:0,fWindowHeight:0,fCw:800,fCh:500,fCatt:b.Create("TAttCanvas"),kMoveOpaque:true,kResizeOpaque:true,fHighLightColor:5,fBatch:true,kShowEventStatus:false,kAutoExec:true,kMenuBar:true});break;case"TGeoVolume":b.Create("TNamed",g);b.Create("TAttLine",g);b.Create("TAttFill",g);b.extend(g,{fGeoAtt:0,fFinder:null,fMedium:null,fNodes:null,fNtotal:0,fNumber:0,fRefCount:0,fShape:null,fVoxels:null});break;case"TGeoNode":b.Create("TNamed",g);b.extend(g,{fGeoAtt:0,fMother:null,fNovlp:0,fNumber:0,fOverlaps:null,fVolume:null});break;case"TGeoNodeMatrix":b.Create("TGeoNode",g);b.extend(g,{fMatrix:null});break}g._typename=f;this.addMethods(g);return g};b.CreateTList=function(){return b.Create("TList")};b.CreateTAxis=function(){return b.Create("TAxis")};b.CreateTH1=function(h){var f=b.extend(b.Create("TH1I"),{fName:"dummy_histo_"+this.id_counter++,fTitle:"dummytitle"});if(h!==undefined){f.fNcells=h+2;for(var g=0;g0){k.fMaxSize=k.fNpoints=m;var j=(typeof f=="object")&&(f.length===m);var h=(typeof l=="object")&&(l.length===m);for(var g=0;g=0){l=l.replace(this.formulas[k].fName,this.formulas[k].fTitle)}}}l=l.replace(/\b(abs)\b/g,"TMath::Abs");l=l.replace("TMath::Exp(","Math.exp(");l=l.replace("TMath::Abs(","Math.abs(");if(typeof b.Math=="object"){this._math=b.Math;l=l.replace("TMath::Prob(","this._math.Prob(");l=l.replace("TMath::Gaus(","this._math.Gaus(");l=l.replace("gaus(","this._math.gaus(this, x, ");l=l.replace("gausn(","this._math.gausn(this, x, ");l=l.replace("expo(","this._math.expo(this, x, ");l=l.replace("landau(","this._math.landau(this, x, ");l=l.replace("landaun(","this._math.landaun(this, x, ")}l=l.replace("pi","Math.PI");for(var k=0;k=p)||(q[l]=p)){if(k[m]+(p-q[m])/(q[l]-q[m])*(k[l]-k[m])=this.fNcells){j=this.fNcells-1}if(j<0){j=0}if(j=0)&&(j=this.fNcells){return 0}if(this.fBinEntries[j]<1e-300){return 0}if(!this.fArray){return 0}return this.fArray[j]/this.fBinEntries[j]};f.getBinEffectiveEntries=function(l){if(l<0||l>=this.fNcells){return 0}var k=this.fBinEntries[l];if(this.fBinSumw2==null||this.fBinSumw2.length!=this.fNcells){return k}var j=this.fSumw2[l];return(j>0?k*k/j:0)};f.getBinError=function(q){if(q<0||q>=this.fNcells){return 0}var r=this.fArray[q],n=this.fBinEntries[q],o=this.fSumw2[q],k=this.getBinEffectiveEntries(q);if(n<1e-300){return 0}var p={kERRORMEAN:0,kERRORSPREAD:1,kERRORSPREADI:2,kERRORSPREADG:3};if(this.fErrorMode===p.kERRORSPREADG){return 1/Math.sqrt(n)}var m=r/n;var j=Math.abs(o/n-m*m);var l=Math.sqrt(j);if(this.fErrorMode===p.kERRORSPREADI){if(l!=0){return l/Math.sqrt(k)}return 1/Math.sqrt(12*k)}if(this.fErrorMode===p.kERRORSPREAD){return l}return(l/Math.sqrt(k))}}if(h=="TAxis"){f.GetBinLowEdge=function(j){if(this.fNbins<=0){return 0}if((this.fXbins.length>0)&&(j>0)&&(j<=this.fNbins)){return this.fXbins[j-1]}return this.fXmin+(j-1)*(this.fXmax-this.fXmin)/this.fNbins}}b.methodsCache[h]=f;return f};b.addMethods=function(f){this.extend(f,b.getMethods(f._typename,f))};b.lastFFormat="";b.FFormat=function(p,h){if(!h){h="6.4g"}b.lastFFormat="";h=h.trim();var m=h.length;if(m<2){return p.toFixed(4)}var q=h.charAt(m-1);h=h.slice(0,m-1);var g=null;var f=h.indexOf(".");if(f<0){f=4}else{f=Number(h.slice(f+1))}if(isNaN(f)||(f<0)||(f==null)){f=4}var r=false;if((q=="e")||(q=="E")){g=true}else{if(q=="Q"){g=true;r=true}else{if((q=="f")||(q=="F")){g=false}else{if(q=="W"){g=false;r=true}else{if((q=="g")||(q=="G")){var n=b.FFormat(p,h+"Q");var j=b.lastFFormat;var k=b.FFormat(p,h+"W");if(n.length0)){f=20;k=p.toFixed(f)}var i=0;while((ii){o--}if(o!=0){f-=o;if(f<0){f=0}else{if(f>20){f=20}}k=p.toFixed(f)}}b.lastFFormat="5."+f+"f";return k};b.log10=function(f){return Math.log(f)/Math.log(10)};b.progress=function(f){if((f!==undefined)&&(typeof f=="string")){b.console(f)}};b.Initialize=function(){if(b.source_fullpath.length===0){return this}function h(l){if(l!=null){if(document.attachEvent?document.readyState==="complete":document.readyState!=="loading"){l()}else{window.onload=l}}return b}var k=b.source_fullpath;if(b.GetUrlOption("gui",k)!==null){return h(function(){b.BuildSimpleGUI()})}if(typeof define==="function"&&define.amd){return h(function(){b.BuildSimpleGUI("check_existing_elements")})}var g="";if(b.GetUrlOption("io",k)!=null){g+="io;"}if(b.GetUrlOption("2d",k)!=null){g+="2d;"}if(b.GetUrlOption("jq2d",k)!=null){g+="jq2d;"}if(b.GetUrlOption("more2d",k)!=null){g+="more2d;"}if(b.GetUrlOption("geo",k)!=null){g+="geo;"}if(b.GetUrlOption("3d",k)!=null){g+="3d;"}if(b.GetUrlOption("math",k)!=null){g+="math;"}if(b.GetUrlOption("mathjax",k)!=null){g+="mathjax;"}var f=b.GetUrlOption("load",k);if((f!=null)&&(f.length>0)){g+="load:"+f}var i=b.GetUrlOption("onload",k);var j=b.GetUrlOption("bower",k);if(j!==null){if(j.length>0){b.bower_dir=j}else{if(b.source_dir.indexOf("jsroot/")==b.source_dir.length-7){b.bower_dir=b.source_dir.substr(0,b.source_dir.length-7)}}if(b.bower_dir.length>0){console.log("Set JSROOT.bower_dir to "+b.bower_dir)}}if((g.length>0)||(i!=null)){h(function(){if(g.length>0){b.AssertPrerequisites(g,i)}else{if(i!=null){i=b.findFunction(i);if(typeof i=="function"){i()}}}})}return this};return b.Initialize()})); \ No newline at end of file diff --git a/visualisations/JsRoot460/scripts/JSRootGeoBase.js b/visualisations/JsRoot460/scripts/JSRootGeoBase.js new file mode 100644 index 0000000..15941af --- /dev/null +++ b/visualisations/JsRoot460/scripts/JSRootGeoBase.js @@ -0,0 +1,3534 @@ +/** @file JSRootGeoBase.js */ +/// Basic functions for work with TGeo classes + +(function( factory ) { + if ( typeof define === "function" && define.amd ) { + // AMD. Register as an anonymous module. + define( [ 'JSRootCore', 'threejs', 'ThreeCSG' ], factory ); + } else { + + if (typeof JSROOT == 'undefined') + throw new Error('JSROOT is not defined', 'JSRootGeoBase.js'); + + if (typeof THREE == 'undefined') + throw new Error('THREE is not defined', 'JSRootGeoBase.js'); + + factory(JSROOT); + } +} (function( JSROOT ) { + // === functions to create THREE.Geometry for TGeo shapes ======================== + + /** @namespace JSROOT.GEO */ + /// Holder of all TGeo-related functions and classes + JSROOT.GEO = { + GradPerSegm: 6, // grad per segment in cylined/spherical symetry shapes + CompressComp: true // use faces compression in composite shapes + }; + + /** @memberOf JSROOT.GEO */ + JSROOT.GEO.BITS = { + kVisOverride : JSROOT.BIT(0), // volume's vis. attributes are overidden + kVisNone : JSROOT.BIT(1), // the volume/node is invisible, as well as daughters + kVisThis : JSROOT.BIT(2), // this volume/node is visible + kVisDaughters : JSROOT.BIT(3), // all leaves are visible + kVisOneLevel : JSROOT.BIT(4), // first level daughters are visible + kVisStreamed : JSROOT.BIT(5), // true if attributes have been streamed + kVisTouched : JSROOT.BIT(6), // true if attributes are changed after closing geom + kVisOnScreen : JSROOT.BIT(7), // true if volume is visible on screen + kVisContainers : JSROOT.BIT(12), // all containers visible + kVisOnly : JSROOT.BIT(13), // just this visible + kVisBranch : JSROOT.BIT(14), // only a given branch visible + kVisRaytrace : JSROOT.BIT(15) // raytracing flag + }; + + /** @memberOf JSROOT.GEO */ + JSROOT.GEO.TestBit = function(volume, f) { + var att = volume.fGeoAtt; + return att === undefined ? false : ((att & f) !== 0); + } + + /** @memberOf JSROOT.GEO */ + JSROOT.GEO.SetBit = function(volume, f, value) { + if (volume.fGeoAtt === undefined) return; + volume.fGeoAtt = value ? (volume.fGeoAtt | f) : (volume.fGeoAtt & ~f); + } + + /** @memberOf JSROOT.GEO */ + JSROOT.GEO.ToggleBit = function(volume, f) { + if (volume.fGeoAtt !== undefined) + volume.fGeoAtt = volume.fGeoAtt ^ (f & 0xffffff); + } + + /** method used to avoid duplication of warnings + * @memberOf JSROOT.GEO */ + JSROOT.GEO.warn = function(msg) { + if (JSROOT.GEO._warn_msgs === undefined) JSROOT.GEO._warn_msgs = {}; + if (JSROOT.GEO._warn_msgs[msg] !== undefined) return; + JSROOT.GEO._warn_msgs[msg] = true; + console.warn(msg); + } + + /** @memberOf JSROOT.GEO */ + JSROOT.GEO.NodeKind = function(obj) { + // return kind of the geo nodes + // 0 - TGeoNode + // 1 - TEveGeoNode + // -1 - unsupported type + + if ((obj === undefined) || (obj === null) || (typeof obj !== 'object')) return -1; + + return ('fShape' in obj) && ('fTrans' in obj) ? 1 : 0; + } + + /** @memberOf JSROOT.GEO */ + JSROOT.GEO.getNodeProperties = function(kind, node, visible) { + // function return different properties for specified node + // Only if node visible, material will be created + + if (kind === 1) { + // special handling for EVE nodes + + var prop = { name: node.fName, nname: node.fName, shape: node.fShape, material: null, chlds: null }; + + if (node.fElements !== null) prop.chlds = node.fElements.arr; + + if (visible) { + var _transparent = false, _opacity = 1.0; + if ( node.fRGBA[3] < 1.0) { + _transparent = true; + _opacity = node.fRGBA[3]; + } + prop.fillcolor = new THREE.Color( node.fRGBA[0], node.fRGBA[1], node.fRGBA[2] ); + prop.material = new THREE.MeshLambertMaterial( { transparent: _transparent, + opacity: _opacity, wireframe: false, color: prop.fillcolor, + side: THREE.FrontSide /* THREE.DoubleSide*/, vertexColors: THREE.NoColors /*THREE.VertexColors */, + overdraw: 0. } ); + prop.material.alwaysTransparent = _transparent; + prop.material.inherentOpacity = _opacity; + } + + return prop; + } + + var volume = node.fVolume; + + var prop = { name: volume.fName, nname: node.fName, volume: node.fVolume, shape: volume.fShape, material: null, chlds: null }; + + if (node.fVolume.fNodes !== null) prop.chlds = node.fVolume.fNodes.arr; + + if (visible) { + var _transparent = false, _opacity = 1.0; + if ((volume.fFillColor > 1) && (volume.fLineColor == 1)) + prop.fillcolor = JSROOT.Painter.root_colors[volume.fFillColor]; + else + if (volume.fLineColor >= 0) + prop.fillcolor = JSROOT.Painter.root_colors[volume.fLineColor]; + + if (volume.fMedium && volume.fMedium.fMaterial) { + var fillstyle = volume.fMedium.fMaterial.fFillStyle; + var transparency = (fillstyle < 3000 || fillstyle > 3100) ? 0 : fillstyle - 3000; + if (transparency > 0) { + _transparent = true; + _opacity = (100.0 - transparency) / 100.0; + } + if (prop.fillcolor === undefined) + prop.fillcolor = JSROOT.Painter.root_colors[volume.fMedium.fMaterial.fFillColor]; + } + if (prop.fillcolor === undefined) + prop.fillcolor = "lightgrey"; + + prop.material = new THREE.MeshLambertMaterial( { transparent: _transparent, + opacity: _opacity, wireframe: false, color: prop.fillcolor, + side: THREE.FrontSide /* THREE.DoubleSide */, vertexColors: THREE.NoColors /*THREE.VertexColors*/, + overdraw: 0. } ); + prop.material.alwaysTransparent = _transparent; + prop.material.inherentOpacity = _opacity; + } + + return prop; + } + + // ========================================================================== + + JSROOT.GEO.GeometryCreator = function(numfaces) { + this.nfaces = numfaces; + this.indx = 0; + this.pos = new Float32Array(numfaces*9); + this.norm = new Float32Array(numfaces*9); + + return this; + } + + JSROOT.GEO.GeometryCreator.prototype.AddFace3 = function(x1,y1,z1, + x2,y2,z2, + x3,y3,z3) { + var indx = this.indx, pos = this.pos; + pos[indx] = x1; + pos[indx+1] = y1; + pos[indx+2] = z1; + pos[indx+3] = x2; + pos[indx+4] = y2; + pos[indx+5] = z2; + pos[indx+6] = x3; + pos[indx+7] = y3; + pos[indx+8] = z3; + this.last4 = false; + this.indx = indx + 9; + } + + JSROOT.GEO.GeometryCreator.prototype.StartPolygon = function() {} + JSROOT.GEO.GeometryCreator.prototype.StopPolygon = function() {} + + JSROOT.GEO.GeometryCreator.prototype.AddFace4 = function(x1,y1,z1, + x2,y2,z2, + x3,y3,z3, + x4,y4,z4, + reduce) { + // from four vertices one normally creates two faces (1,2,3) and (1,3,4) + // if (reduce==1), first face is reduced + // if (reduce==2), second face is reduced + + var indx = this.indx, pos = this.pos; + + if (reduce!==1) { + pos[indx] = x1; + pos[indx+1] = y1; + pos[indx+2] = z1; + pos[indx+3] = x2; + pos[indx+4] = y2; + pos[indx+5] = z2; + pos[indx+6] = x3; + pos[indx+7] = y3; + pos[indx+8] = z3; + indx+=9; + } + + if (reduce!==2) { + pos[indx] = x1; + pos[indx+1] = y1; + pos[indx+2] = z1; + pos[indx+3] = x3; + pos[indx+4] = y3; + pos[indx+5] = z3; + pos[indx+6] = x4; + pos[indx+7] = y4; + pos[indx+8] = z4; + indx+=9; + } + + this.last4 = (indx !== this.indx + 9); + this.indx = indx; + } + + JSROOT.GEO.GeometryCreator.prototype.SetNormal4 = function(nx1,ny1,nz1, + nx2,ny2,nz2, + nx3,ny3,nz3, + nx4,ny4,nz4, + reduce) { + // same as AddFace4, assign normals for each individual vertex + // reduce has same meening and should be the same + + if (this.last4 && reduce) + return console.error('missmatch between AddFace4 and SetNormal4 calls'); + + var indx = this.indx - (this.last4 ? 18 : 9), norm = this.norm; + + if (reduce!==1) { + norm[indx] = nx1; + norm[indx+1] = ny1; + norm[indx+2] = nz1; + norm[indx+3] = nx2; + norm[indx+4] = ny2; + norm[indx+5] = nz2; + norm[indx+6] = nx3; + norm[indx+7] = ny3; + norm[indx+8] = nz3; + indx+=9; + } + + if (reduce!==2) { + norm[indx] = nx1; + norm[indx+1] = ny1; + norm[indx+2] = nz1; + norm[indx+3] = nx3; + norm[indx+4] = ny3; + norm[indx+5] = nz3; + norm[indx+6] = nx4; + norm[indx+7] = ny4; + norm[indx+8] = nz4; + } + } + + JSROOT.GEO.GeometryCreator.prototype.RecalcZ = function(func) { + var pos = this.pos, + last = this.indx, + indx = last - (this.last4 ? 18 : 9); + + while (indx < last) { + pos[indx+2] = func(pos[indx], pos[indx+1], pos[indx+2]); + indx+=3; + } + } + + JSROOT.GEO.GetNormal = function(x1,y1,z1,x2,y2,z2,x3,y3,z3) { + + var pA = new THREE.Vector3(x1,y1,z1), + pB = new THREE.Vector3(x2,y2,z2), + pC = new THREE.Vector3(x3,y3,z3), + cb = new THREE.Vector3(), + ab = new THREE.Vector3(); + + cb.subVectors( pC, pB ); + ab.subVectors( pA, pB ); + cb.cross(ab ); + + return cb; + } + + JSROOT.GEO.GeometryCreator.prototype.CalcNormal = function() { + var indx = this.indx, norm = this.norm; + + if (!this.cb) { + this.pA = new THREE.Vector3(); + this.pB = new THREE.Vector3(); + this.pC = new THREE.Vector3(); + this.cb = new THREE.Vector3(); + this.ab = new THREE.Vector3(); + } + + this.pA.fromArray( this.pos, this.indx - 9 ); + this.pB.fromArray( this.pos, this.indx - 6 ); + this.pC.fromArray( this.pos, this.indx - 3 ); + + this.cb.subVectors( this.pC, this.pB ); + this.ab.subVectors( this.pA, this.pB ); + this.cb.cross( this.ab ); + + this.SetNormal(this.cb.x, this.cb.y, this.cb.z); + } + + JSROOT.GEO.GeometryCreator.prototype.SetNormal = function(nx,ny,nz) { + var indx = this.indx - 9, norm = this.norm; + + norm[indx] = norm[indx+3] = norm[indx+6] = nx; + norm[indx+1] = norm[indx+4] = norm[indx+7] = ny; + norm[indx+2] = norm[indx+5] = norm[indx+8] = nz; + + if (this.last4) { + indx -= 9; + norm[indx] = norm[indx+3] = norm[indx+6] = nx; + norm[indx+1] = norm[indx+4] = norm[indx+7] = ny; + norm[indx+2] = norm[indx+5] = norm[indx+8] = nz; + } + } + + JSROOT.GEO.GeometryCreator.prototype.SetNormal_12_34 = function(nx12,ny12,nz12,nx34,ny34,nz34,reduce) { + // special shortcut, when same normals can be applied for 1-2 point and 3-4 point + if (reduce===undefined) reduce = 0; + + var indx = this.indx - ((reduce>0) ? 9 : 18), norm = this.norm; + + if (reduce!==1) { + norm[indx] = nx12; + norm[indx+1] = ny12; + norm[indx+2] = nz12; + norm[indx+3] = nx12; + norm[indx+4] = ny12; + norm[indx+5] = nz12; + norm[indx+6] = nx34; + norm[indx+7] = ny34; + norm[indx+8] = nz34; + indx+=9; + } + + if (reduce!==2) { + norm[indx] = nx12; + norm[indx+1] = ny12; + norm[indx+2] = nz12; + norm[indx+3] = nx34; + norm[indx+4] = ny34; + norm[indx+5] = nz34; + norm[indx+6] = nx34; + norm[indx+7] = ny34; + norm[indx+8] = nz34; + indx+=9; + } + } + + + JSROOT.GEO.GeometryCreator.prototype.Create = function() { + if (this.nfaces !== this.indx/9) + console.error('Mismatch with created ' + this.nfaces + ' and filled ' + this.indx/9 + ' number of faces'); + + var geometry = new THREE.BufferGeometry(); + geometry.addAttribute( 'position', new THREE.BufferAttribute( this.pos, 3 ) ); + geometry.addAttribute( 'normal', new THREE.BufferAttribute( this.norm, 3 ) ); + return geometry; + } + + // ================================================================================ + + // same methods as GeometryCreator, but this different implementation + + JSROOT.GEO.PolygonsCreator = function() { + this.polygons = []; + } + + JSROOT.GEO.PolygonsCreator.prototype.StartPolygon = function(normal) { + this.multi = 1; + this.mnormal = normal; + } + + JSROOT.GEO.PolygonsCreator.prototype.StopPolygon = function() { + if (!this.multi) return; + this.multi = 0; + console.error('Polygon should be already closed at this moment'); + } + + JSROOT.GEO.PolygonsCreator.prototype.AddFace3 = function(x1,y1,z1, + x2,y2,z2, + x3,y3,z3) { + this.AddFace4(x1,y1,z1,x2,y2,z2,x3,y3,z3,x3,y3,z3,2); + } + + + JSROOT.GEO.PolygonsCreator.prototype.AddFace4 = function(x1,y1,z1, + x2,y2,z2, + x3,y3,z3, + x4,y4,z4, + reduce) { + // from four vertices one normaly creates two faces (1,2,3) and (1,3,4) + // if (reduce==1), first face is reduced + // if (reduce==2), second face is reduced + + if (reduce === undefined) reduce = 0; + + this.v1 = new ThreeBSP.Vertex( x1, y1, z1, 0, 0, 0 ); + this.v2 = (reduce===1) ? null : new ThreeBSP.Vertex( x2, y2, z2, 0, 0, 0 ); + this.v3 = new ThreeBSP.Vertex( x3, y3, z3, 0, 0, 0 ); + this.v4 = (reduce===2) ? null : new ThreeBSP.Vertex( x4, y4, z4, 0, 0, 0 ); + + this.reduce = reduce; + + if (this.multi) { + //console.log('n',this.multi); + //console.log('v1:' + x1.toFixed(1) + ':' + y1.toFixed(1) + ':'+ z1.toFixed(1)); + //console.log('v2:' + x2.toFixed(1) + ':' + y2.toFixed(1) + ':'+ z2.toFixed(1)); + //console.log('v3:' + x3.toFixed(1) + ':' + y3.toFixed(1) + ':'+ z3.toFixed(1)); + //console.log('v4:' + x4.toFixed(1) + ':' + y4.toFixed(1) + ':'+ z4.toFixed(1)); + + if (reduce!==2) console.error('polygon not supported for not-reduced faces'); + + var polygon; + + if (this.multi++ === 1) { + polygon = new ThreeBSP.Polygon; + + polygon.vertices.push(this.mnormal ? this.v2 : this.v3); + this.polygons.push(polygon); + } else { + polygon = this.polygons[this.polygons.length-1]; + // check that last vertice equals to v2 + var last = this.mnormal ? polygon.vertices[polygon.vertices.length-1] : polygon.vertices[0], + comp = this.mnormal ? this.v2 : this.v3; + + if (comp.diff(last) > 1e-12) + console.error('vertex missmatch when building polygon'); + } + + var first = this.mnormal ? polygon.vertices[0] : polygon.vertices[polygon.vertices.length-1], + next = this.mnormal ? this.v3 : this.v2; + + if (next.diff(first) < 1e-12) { + //console.log('polygon closed!!!', polygon.vertices.length); + this.multi = 0; + } else + if (this.mnormal) { + polygon.vertices.push(this.v3); + } else { + polygon.vertices.unshift(this.v2); + } + + return; + + } + + var polygon = new ThreeBSP.Polygon; + + switch (reduce) { + case 0: polygon.vertices.push(this.v1, this.v2, this.v3, this.v4); break; + case 1: polygon.vertices.push(this.v1, this.v3, this.v4); break; + case 2: polygon.vertices.push(this.v1, this.v2, this.v3); break; + } + + this.polygons.push(polygon); + } + + JSROOT.GEO.PolygonsCreator.prototype.SetNormal4 = function(nx1,ny1,nz1, + nx2,ny2,nz2, + nx3,ny3,nz3, + nx4,ny4,nz4, + reduce) { + this.v1.setnormal(nx1,ny1,nz1); + if (this.v2) this.v2.setnormal(nx2,ny2,nz2); + this.v3.setnormal(nx3,ny3,nz3); + if (this.v4) this.v4.setnormal(nx4,ny4,nz4); + } + + JSROOT.GEO.PolygonsCreator.prototype.SetNormal_12_34 = function(nx12,ny12,nz12,nx34,ny34,nz34,reduce) { + // special shortcut, when same normals can be applied for 1-2 point and 3-4 point + this.v1.setnormal(nx12,ny12,nz12); + if (this.v2) this.v2.setnormal(nx12,ny12,nz12); + this.v3.setnormal(nx34,ny34,nz34); + if (this.v4) this.v4.setnormal(nx34,ny34,nz34); + } + + JSROOT.GEO.PolygonsCreator.prototype.CalcNormal = function() { + + if (!this.cb) { + this.pA = new THREE.Vector3(); + this.pB = new THREE.Vector3(); + this.pC = new THREE.Vector3(); + this.cb = new THREE.Vector3(); + this.ab = new THREE.Vector3(); + } + + this.pA.set( this.v1.x, this.v1.y, this.v1.z); + + if (this.reduce!==1) { + this.pB.set( this.v2.x, this.v2.y, this.v2.z); + this.pC.set( this.v3.x, this.v3.y, this.v3.z); + } else { + this.pB.set( this.v3.x, this.v3.y, this.v3.z); + this.pC.set( this.v4.x, this.v4.y, this.v4.z); + } + + this.cb.subVectors( this.pC, this.pB ); + this.ab.subVectors( this.pA, this.pB ); + this.cb.cross( this.ab ); + + // if (debug) console.log('NORM x', this.cb.x.toFixed(1), ' y ', this.cb.y.toFixed(1), ' z ' , this.cb.z.toFixed(1)); + + this.SetNormal(this.cb.x, this.cb.y, this.cb.z); + } + + + JSROOT.GEO.PolygonsCreator.prototype.SetNormal = function(nx,ny,nz) { + this.v1.setnormal(nx,ny,nz); + if (this.v2) this.v2.setnormal(nx,ny,nz); + this.v3.setnormal(nx,ny,nz); + if (this.v4) this.v4.setnormal(nx,ny,nz); + } + + JSROOT.GEO.PolygonsCreator.prototype.RecalcZ = function(func) { + this.v1.z = func(this.v1.x, this.v1.y, this.v1.z); + if (this.v2) this.v2.z = func(this.v2.x, this.v2.y, this.v2.z); + this.v3.z = func(this.v3.x, this.v3.y, this.v3.z); + if (this.v4) this.v4.z = func(this.v4.x, this.v4.y, this.v4.z); + } + + JSROOT.GEO.PolygonsCreator.prototype.Create = function() { + return { polygons: this.polygons }; + } + + // ================= all functions to create geometry =================================== + + /** @memberOf JSROOT.GEO */ + JSROOT.GEO.createCube = function( shape ) { + + // instead of BoxGeometry create all vertices and faces ourself + // reduce number of allocated objects + + //return new THREE.BoxGeometry( 2*shape.fDX, 2*shape.fDY, 2*shape.fDZ ); + + var geom = new THREE.Geometry(); + + geom.vertices.push( new THREE.Vector3( shape.fDX, shape.fDY, shape.fDZ ) ); + geom.vertices.push( new THREE.Vector3( shape.fDX, shape.fDY, -shape.fDZ ) ); + geom.vertices.push( new THREE.Vector3( shape.fDX, -shape.fDY, shape.fDZ ) ); + geom.vertices.push( new THREE.Vector3( shape.fDX, -shape.fDY, -shape.fDZ ) ); + geom.vertices.push( new THREE.Vector3(-shape.fDX, shape.fDY, -shape.fDZ ) ); + geom.vertices.push( new THREE.Vector3(-shape.fDX, shape.fDY, shape.fDZ ) ); + geom.vertices.push( new THREE.Vector3(-shape.fDX, -shape.fDY, -shape.fDZ ) ); + geom.vertices.push( new THREE.Vector3(-shape.fDX, -shape.fDY, shape.fDZ ) ); + + var indicies = [0,2,1, 2,3,1, 4,6,5, 6,7,5, 4,5,1, 5,0,1, 7,6,2, 6,3,2, 5,7,0, 7,2,0, 1,3,4, 3,6,4]; + + // normals for each pair of faces + var normals = [ 1,0,0, -1,0,0, 0,1,0, 0,-1,0, 0,0,1, 0,0,-1 ]; + + var color = new THREE.Color(); + var norm = null; + for (var n=0; n < indicies.length; n+=3) { + if (n % 6 === 0) norm = new THREE.Vector3(normals[n/2], normals[n/2+1], normals[n/2+2]); + var face = new THREE.Face3( indicies[n], indicies[n+1], indicies[n+2], norm, color, 0); + geom.faces.push(face); + } + + return geom; + } + + /** @memberOf JSROOT.GEO */ + JSROOT.GEO.createCubeBuffer = function( shape, faces_limit) { + + if (faces_limit < 0) return 12; + + var dx = shape.fDX, dy = shape.fDY, dz = shape.fDZ; + + var creator = faces_limit ? new JSROOT.GEO.PolygonsCreator : new JSROOT.GEO.GeometryCreator(12); + + // var creator = new JSROOT.GEO.GeometryCreator(12); + + creator.AddFace4(dx,dy,dz, dx,-dy,dz, dx,-dy,-dz, dx,dy,-dz); creator.SetNormal(1,0,0); + + creator.AddFace4(-dx,dy,-dz, -dx,-dy,-dz, -dx,-dy,dz, -dx,dy,dz); creator.SetNormal(-1,0,0); + + creator.AddFace4(-dx,dy,-dz, -dx,dy,dz, dx,dy,dz, dx,dy,-dz); creator.SetNormal(0,1,0); + + creator.AddFace4(-dx,-dy,dz, -dx,-dy,-dz, dx,-dy,-dz, dx,-dy,dz); creator.SetNormal(0,-1,0); + + creator.AddFace4(-dx,dy,dz, -dx,-dy,dz, dx,-dy,dz, dx,dy,dz); creator.SetNormal(0,0,1); + + creator.AddFace4(dx,dy,-dz, dx,-dy,-dz, -dx,-dy,-dz, -dx,dy,-dz); creator.SetNormal(0,0,-1); + + return creator.Create(); + } + + /** @memberOf JSROOT.GEO */ + JSROOT.GEO.createPara = function( shape ) { + + var txy = shape.fTxy, txz = shape.fTxz, tyz = shape.fTyz; + + var verticesOfShape = [ + -shape.fZ*txz-txy*shape.fY-shape.fX, -shape.fY-shape.fZ*tyz, -shape.fZ, + -shape.fZ*txz+txy*shape.fY-shape.fX, shape.fY-shape.fZ*tyz, -shape.fZ, + -shape.fZ*txz+txy*shape.fY+shape.fX, shape.fY-shape.fZ*tyz, -shape.fZ, + -shape.fZ*txz-txy*shape.fY+shape.fX, -shape.fY-shape.fZ*tyz, -shape.fZ, + shape.fZ*txz-txy*shape.fY-shape.fX, -shape.fY+shape.fZ*tyz, shape.fZ, + shape.fZ*txz+txy*shape.fY-shape.fX, shape.fY+shape.fZ*tyz, shape.fZ, + shape.fZ*txz+txy*shape.fY+shape.fX, shape.fY+shape.fZ*tyz, shape.fZ, + shape.fZ*txz-txy*shape.fY+shape.fX, -shape.fY+shape.fZ*tyz, shape.fZ ]; + + var indicesOfFaces = [ 4,6,5, 4,7,6, 0,3,7, 7,4,0, + 4,5,1, 1,0,4, 6,2,1, 1,5,6, + 7,3,2, 2,6,7, 1,2,3, 3,0,1 ]; + + var geom = new THREE.Geometry(); + + for (var i = 0; i < verticesOfShape.length; i += 3) + geom.vertices.push( new THREE.Vector3( verticesOfShape[i], verticesOfShape[i+1], verticesOfShape[i+2] ) ); + + var color = new THREE.Color(); + + for (var i = 0; i < indicesOfFaces.length; i += 3) + geom.faces.push( new THREE.Face3( indicesOfFaces[i], indicesOfFaces[i+1], indicesOfFaces[i+2], null, color, 0 ) ); + + geom.computeFaceNormals(); + + return geom; + } + + /** @memberOf JSROOT.GEO */ + JSROOT.GEO.create8edgesBuffer = function( v, faces_limit ) { + + var indicies = [ 4,7,6,5, 0,3,7,4, 4,5,1,0, 6,2,1,5, 7,3,2,6, 1,2,3,0 ]; + + var creator = (faces_limit > 0) ? new JSROOT.GEO.PolygonsCreator : new JSROOT.GEO.GeometryCreator(12); + + // var creator = new JSROOT.GEO.GeometryCreator(12); + + for (var n=0;n=0) || (map.indexOf(id2)>=0) || (map.indexOf(id3)>=0)) { + indicies[k] = indicies[k+1] = indicies[k+2] = -1; + } else { + map.push(id1,id2,id3); + usage[indicies[k]]++; + usage[indicies[k+1]]++; + usage[indicies[k+2]]++; + } + } + + var geometry = new THREE.Geometry(); + for (var i = 0; i < 8; ++i) { + if (usage[i] > 0) { + usage[i] = geometry.vertices.length; // use array to remap old vertices + geometry.vertices.push( new THREE.Vector3( vertices[i*3], vertices[i*3+1], vertices[i*3+2] ) ); + } + else { + usage[i] = -1; + } + } + + var color = new THREE.Color(); + + for (var i = 0; i < 36; i += 3) { + if (indicies[i]<0) continue; + + var a = usage[indicies[i]], + b = usage[indicies[i+1]], + c = usage[indicies[i+2]]; + + geometry.faces.push( new THREE.Face3( a, b, c, null, color, 0 ) ); + } + + geometry.computeFaceNormals(); + return geometry; + } + + /** @memberOf JSROOT.GEO */ + JSROOT.GEO.createArb8Buffer = function( shape, faces_limit ) { + + if (faces_limit < 0) return 12; + + var vertices = [ + shape.fXY[0][0], shape.fXY[0][1], -shape.fDZ, + shape.fXY[1][0], shape.fXY[1][1], -shape.fDZ, + shape.fXY[2][0], shape.fXY[2][1], -shape.fDZ, + shape.fXY[3][0], shape.fXY[3][1], -shape.fDZ, + shape.fXY[4][0], shape.fXY[4][1], shape.fDZ, + shape.fXY[5][0], shape.fXY[5][1], shape.fDZ, + shape.fXY[6][0], shape.fXY[6][1], shape.fDZ, + shape.fXY[7][0], shape.fXY[7][1], shape.fDZ + ]; + + var indicies = [ + 4,7,6, 6,5,4, 0,3,7, 7,4,0, + 4,5,1, 1,0,4, 6,2,1, 1,5,6, + 7,3,2, 2,6,7, 1,2,3, 3,0,1 ]; + + // var face4 = [ 4,7,6,5, 0,3,7,4, 4,5,1,0, 6,2,1,5, 7,3,2,6, 1,2,3,0 ]; + + // detect same vertecies on both Z-layers + for (var side=0;side=0) || (map.indexOf(id2)>=0) || (map.indexOf(id3)>=0)) { + indicies[k] = indicies[k+1] = indicies[k+2] = -1; + } else { + map.push(id1,id2,id3); + numfaces++; + } + } + + var creator = faces_limit ? new JSROOT.GEO.PolygonsCreator : new JSROOT.GEO.GeometryCreator(numfaces); + + // var creator = new JSROOT.GEO.GeometryCreator(numfaces); + + for (var n=0; n < indicies.length; n+=6) { + var i1 = indicies[n] * 3, + i2 = indicies[n+1] * 3, + i3 = indicies[n+2] * 3, + i4 = indicies[n+3] * 3, + i5 = indicies[n+4] * 3, + i6 = indicies[n+5] * 3, + norm = null; + + if ((i1>=0) && (i4>=0) && faces_limit) { + // try to identify two faces with same normal - very useful if one can create face4 + if (n===0) norm = new THREE.Vector3(0,0,1); else + if (n===30) norm = new THREE.Vector3(0,0,-1); else { + var norm1 = JSROOT.GEO.GetNormal(vertices[i1], vertices[i1+1], vertices[i1+2], + vertices[i2], vertices[i2+1], vertices[i2+2], + vertices[i3], vertices[i3+1], vertices[i3+2]); + + norm1.normalize(); + + var norm2 = JSROOT.GEO.GetNormal(vertices[i4], vertices[i4+1], vertices[i4+2], + vertices[i5], vertices[i5+1], vertices[i5+2], + vertices[i6], vertices[i6+1], vertices[i6+2]); + + norm2.normalize(); + + if (norm1.distanceToSquared(norm2) < 1e-12) norm = norm1; + } + } + + if (norm !== null) { + creator.AddFace4(vertices[i1], vertices[i1+1], vertices[i1+2], + vertices[i2], vertices[i2+1], vertices[i2+2], + vertices[i3], vertices[i3+1], vertices[i3+2], + vertices[i5], vertices[i5+1], vertices[i5+2]); + creator.SetNormal(norm.x, norm.y, norm.z); + } else { + if (i1>=0) { + creator.AddFace3(vertices[i1], vertices[i1+1], vertices[i1+2], + vertices[i2], vertices[i2+1], vertices[i2+2], + vertices[i3], vertices[i3+1], vertices[i3+2]); + creator.CalcNormal(); + } + if (i4>=0) { + creator.AddFace3(vertices[i4], vertices[i4+1], vertices[i4+2], + vertices[i5], vertices[i5+1], vertices[i5+2], + vertices[i6], vertices[i6+1], vertices[i6+2]); + creator.CalcNormal(); + } + } + } + + return creator.Create(); + } + + /** @memberOf JSROOT.GEO */ + JSROOT.GEO.createSphere = function( shape, faces_limit ) { + var outerRadius = shape.fRmax, + innerRadius = shape.fRmin, + phiStart = shape.fPhi1 + 180, + phiLength = shape.fPhi2 - shape.fPhi1, + thetaStart = shape.fTheta1, + thetaLength = shape.fTheta2 - shape.fTheta1, + widthSegments = shape.fNseg, + heightSegments = shape.fNz; + + var noInside = (innerRadius <= 0); + + while (phiStart >= 360) phiStart-=360; + + if (faces_limit > 0) { + + var fact = (noInside ? 2 : 4) * widthSegments * heightSegments / faces_limit; + + if (fact > 1.) { + widthSegments = Math.round(widthSegments/Math.sqrt(fact)); + heightSegments = Math.round(heightSegments/Math.sqrt(fact)); + } + } + + var sphere = new THREE.SphereGeometry( outerRadius, widthSegments, heightSegments, + phiStart*Math.PI/180, phiLength*Math.PI/180, thetaStart*Math.PI/180, thetaLength*Math.PI/180); + sphere.applyMatrix( new THREE.Matrix4().makeRotationX( Math.PI / 2 ) ); + + var geometry = new THREE.Geometry(); + var color = new THREE.Color(); + + // add outer sphere + for (var n=0; n < sphere.vertices.length; ++n) + geometry.vertices.push(sphere.vertices[n]); + + // add faces + for (var n=0; n < sphere.faces.length; ++n) { + var face = sphere.faces[n]; + geometry.faces.push(new THREE.Face3( face.a, face.b, face.c, null, color, 0 ) ); + } + + var shift = geometry.vertices.length; + + if (noInside) { + // simple sphere without inner cut + if ((thetaLength === 180) && (phiLength === 360)) { + geometry.computeFaceNormals(); + return geometry; + } + + geometry.vertices.push(new THREE.Vector3(0, 0, 0)); + } else { + var k = innerRadius / outerRadius; + + // add inner sphere + for (var n=0; n < sphere.vertices.length; ++n) { + var v = sphere.vertices[n]; + geometry.vertices.push(new THREE.Vector3(k*v.x, k*v.y, k*v.z)); + } + for (var n=0; n < sphere.faces.length; ++n) { + var face = sphere.faces[n]; + geometry.faces.push(new THREE.Face3( shift+face.b, shift+face.a, shift+face.c, null, color, 0 ) ); + } + } + + if (thetaLength !== 180) { + // add top cap + for (var i = 0; i < widthSegments; ++i) { + if (noInside) { + geometry.faces.push( new THREE.Face3( i+0, i+1, shift, null, color, 0 ) ); + } else { + geometry.faces.push( new THREE.Face3( i+0, i+1, i+shift, null, color, 0 ) ); + geometry.faces.push( new THREE.Face3( i+1, i+shift+1, i+shift, null, color, 0 ) ); + } + } + + var dshift = sphere.vertices.length - widthSegments - 1; + + // add bottom cap + for (var i = dshift; i < dshift + widthSegments; ++i) { + if (noInside) { + geometry.faces.push( new THREE.Face3( i+0, i+1, shift, null, color, 0 ) ); + } else { + geometry.faces.push( new THREE.Face3( i+1, i+0, i+shift, null, color, 0 ) ); + geometry.faces.push( new THREE.Face3( i+shift+1, i+1, i+shift, null, color, 0 ) ); + } + } + } + + if (phiLength !== 360) { + // one cuted side + for (var j=0; j 0) { + var fact = (noInside ? 2 : 4) * widthSegments * heightSegments / faces_limit; + + if (fact > 1.) { + widthSegments = Math.max(4, Math.floor(widthSegments/Math.sqrt(fact))); + heightSegments = Math.max(4, Math.floor(heightSegments/Math.sqrt(fact))); + } + } + + var numoutside = widthSegments * heightSegments * 2, + numtop = widthSegments * 2, + numbottom = widthSegments * 2, + numcut = phiLength === 360 ? 0 : heightSegments * (noInside ? 2 : 4), + epsilon = 1e-10; + + if (noInside) numbottom = numtop = widthSegments; + + if (faces_limit < 0) return numoutside * (noInside ? 1 : 2) + numtop + numbottom + numcut; + + var _sinp = new Float32Array(widthSegments+1), + _cosp = new Float32Array(widthSegments+1), + _sint = new Float32Array(heightSegments+1), + _cost = new Float32Array(heightSegments+1); + + for (var n=0;n<=heightSegments;++n) { + var theta = (thetaStart + thetaLength/heightSegments*n)*Math.PI/180; + _sint[n] = Math.sin(theta); + _cost[n] = Math.cos(theta); + } + + for (var n=0;n<=widthSegments;++n) { + var phi = (phiStart + phiLength/widthSegments*n)*Math.PI/180; + _sinp[n] = Math.sin(phi); + _cosp[n] = Math.cos(phi); + } + + if (Math.abs(_sint[0]) <= epsilon) { numoutside -= widthSegments; numtop = 0; } + if (Math.abs(_sint[heightSegments]) <= epsilon) { numoutside -= widthSegments; numbottom = 0; } + + var numfaces = numoutside * (noInside ? 1 : 2) + numtop + numbottom + numcut; + + var creator = faces_limit ? new JSROOT.GEO.PolygonsCreator : new JSROOT.GEO.GeometryCreator(numfaces); + + // var creator = new JSROOT.GEO.GeometryCreator(numfaces); + + for (var side=0;side<2;++side) { + if ((side===1) && noInside) break; + + var r = radius[side], + s = (side===0) ? 1 : -1, + d1 = 1 - side, d2 = 1 - d1; + + // use direct algorithm for the sphere - here normals and position can be calculated direclty + for (var k=0;k= epsilon) { + var ss = _sint[side], cc = _cost[side], + d1 = (side===0) ? 0 : 1, d2 = 1 - d1; + for (var n=0;n 0) || (innerRadius2 > 0); + + if (hasrmin) { + if (innerRadius1 <= 0) { innerRadius1 = 0.0000001; JSROOT.GEO.warn('zero inner radius1 in tube - not yet supported'); } + if (innerRadius2 <= 0) { innerRadius2 = 0.0000001; JSROOT.GEO.warn('zero inner radius1 in tube - not yet supported'); } + } + + var thetaStart = 0, thetaLength = 360; + if ((shape._typename == "TGeoConeSeg") || (shape._typename == "TGeoTubeSeg") || (shape._typename == "TGeoCtub")) { + thetaStart = shape.fPhi1; + thetaLength = shape.fPhi2 - shape.fPhi1; + } + + var radiusSegments = Math.round(thetaLength/JSROOT.GEO.GradPerSegm); + if (radiusSegments < 4) radiusSegments = 4; + + var extrapnt = (thetaLength < 360) ? 1 : 0; + + var nsegm = radiusSegments + extrapnt; + + var phi0 = thetaStart*Math.PI/180, dphi = thetaLength/radiusSegments*Math.PI/180; + + // calculate all sin/cos tables in advance + var _sin = new Float32Array(nsegm), _cos = new Float32Array(nsegm); + for (var seg=0; seg 0) || (innerR[1] > 0); + + var thetaStart = 0, thetaLength = 360; + if ((shape._typename == "TGeoConeSeg") || (shape._typename == "TGeoTubeSeg") || (shape._typename == "TGeoCtub")) { + thetaStart = shape.fPhi1; + thetaLength = shape.fPhi2 - shape.fPhi1; + } + + var radiusSegments = Math.max(4, Math.round(thetaLength/JSROOT.GEO.GradPerSegm)); + + // external surface + var numfaces = radiusSegments * (((outerR[0] <= 0) || (outerR[1] <= 0)) ? 1 : 2); + + // internal surface + if (hasrmin) + numfaces += radiusSegments * (((innerR[0] <= 0) || (innerR[1] <= 0)) ? 1 : 2); + + // upper cap + if (outerR[0] > 0) numfaces += radiusSegments * ((innerR[0]>0) ? 2 : 1); + // bottom cup + if (outerR[1] > 0) numfaces += radiusSegments * ((innerR[1]>0) ? 2 : 1); + + if (thetaLength < 360) + numfaces += ((outerR[0] > innerR[0]) ? 2 : 0) + ((outerR[1] > innerR[1]) ? 2 : 0); + + if (faces_limit < 0) return numfaces; + + var phi0 = thetaStart*Math.PI/180, + dphi = thetaLength/radiusSegments*Math.PI/180, + _sin = new Float32Array(radiusSegments+1), + _cos = new Float32Array(radiusSegments+1); + + for (var seg=0; seg<=radiusSegments; ++seg) { + _cos[seg] = Math.cos(phi0+seg*dphi); + _sin[seg] = Math.sin(phi0+seg*dphi); + } + + var creator = faces_limit ? new JSROOT.GEO.PolygonsCreator : new JSROOT.GEO.GeometryCreator(numfaces); + + // var creator = new JSROOT.GEO.GeometryCreator(numfaces); + + var calcZ; + + if (shape._typename == "TGeoCtub") + calcZ = function(x,y,z) { + var arr = (z<0) ? shape.fNlow : shape.fNhigh; + return ((z<0) ? -shape.fDz : shape.fDz) - (x*arr[0] + y*arr[1]) / arr[2]; + } + + // create outer/inner tube + for (var side = 0; side<2; ++side) { + if ((side === 1) && !hasrmin) break; + + var R = (side === 0) ? outerR : innerR, + d1 = side, d2 = 1 - side, nxy = 1., nz = 0; + + if (R[0] !== R[1]) { + var angle = Math.atan2((R[1]-R[0]), 2*shape.fDZ); + nxy = Math.cos(angle); + nz = Math.sin(angle); + } + + if (side === 1) { nxy *= -1; nz *= -1; }; + + var reduce = 0; + if (R[0] <= 0) reduce = 2; else + if (R[1] <= 0) reduce = 1; + + for (var seg=0;seg 0, hascut = (arc !== 360); + + if (faces_limit < 0) return (hasrmin ? 4 : 2) * (radialSegments + 1) * tubularSegments; + + if (faces_limit > 0) { + var fact = (hasrmin ? 4 : 2) * (radialSegments + 1) * tubularSegments / faces_limit; + if (fact > 1.) { + radialSegments = Math.round(radialSegments/Math.sqrt(fact)); + tubularSegments = Math.round(tubularSegments/Math.sqrt(fact)); + } + } + + var geometry = new THREE.Geometry(); + var color = new THREE.Color(); + + var outerTorus = new THREE.TorusGeometry( radius, outerTube, radialSegments, tubularSegments, arc*Math.PI/180); + outerTorus.applyMatrix( new THREE.Matrix4().makeRotationZ(rotation*Math.PI/180) ); + + // add outer torus + for (var n=0; n < outerTorus.vertices.length; ++n) + geometry.vertices.push(outerTorus.vertices[n]); + + for (var n=0; n < outerTorus.faces.length; ++n) { + var face = outerTorus.faces[n]; + geometry.faces.push(new THREE.Face3( face.a, face.b, face.c, null, color, 0 ) ); + } + + var shift = geometry.vertices.length; + + if (hasrmin) { + var innerTorus = new THREE.TorusGeometry( radius, innerTube, radialSegments, tubularSegments, arc*Math.PI/180); + innerTorus.applyMatrix( new THREE.Matrix4().makeRotationZ(rotation*Math.PI/180) ); + + // add inner torus + for (var n=0; n < innerTorus.vertices.length; ++n) + geometry.vertices.push(innerTorus.vertices[n]); + + for (var n=0; n < innerTorus.faces.length; ++n) { + var face = innerTorus.faces[n]; + geometry.faces.push(new THREE.Face3( shift+face.a, shift+face.c, shift+face.b, null, color, 0 ) ); + } + } else + if (hascut) { + geometry.vertices.push(new THREE.Vector3(radius*Math.cos(rotation*Math.PI/180), radius*Math.sin(rotation*Math.PI/180),0)); + geometry.vertices.push(new THREE.Vector3(radius*Math.cos((rotation+arc)*Math.PI/180), radius*Math.sin((rotation+arc)*Math.PI/180),0)); + } + + if (arc !== 360) { + // one cuted side + for (var j=0;j 0 ? 4 : 2) * radialSegments * (tubularSegments + (shape.fDphi !== 360 ? 1 : 0)); + + if (faces_limit < 0) return numfaces; + + if ((faces_limit > 0) && (numfaces > faces_limit)) { + radialSegments = Math.floor(radialSegments/Math.sqrt(numfaces / faces_limit)); + tubularSegments = Math.floor(tubularSegments/Math.sqrt(numfaces / faces_limit)); + numfaces = (shape.fRmin > 0 ? 4 : 2) * radialSegments * (tubularSegments + (shape.fDphi !== 360 ? 1 : 0)); + } + + var _sinr = new Float32Array(radialSegments+1), + _cosr = new Float32Array(radialSegments+1), + _sint = new Float32Array(tubularSegments+1), + _cost = new Float32Array(tubularSegments+1); + + for (var n=0;n<=radialSegments;++n) { + _sinr[n] = Math.sin(n/radialSegments*2*Math.PI); + _cosr[n] = Math.cos(n/radialSegments*2*Math.PI); + } + + for (var t=0;t<=tubularSegments;++t) { + var angle = (shape.fPhi1 + shape.fDphi*t/tubularSegments)/180*Math.PI; + _sint[t] = Math.sin(angle); + _cost[t] = Math.cos(angle); + } + + var creator = faces_limit ? new JSROOT.GEO.PolygonsCreator : new JSROOT.GEO.GeometryCreator(numfaces); + + // use vectors for normals calculation + var p1 = new THREE.Vector3(), p2 = new THREE.Vector3(), p3 = new THREE.Vector3(), p4 = new THREE.Vector3(), + n1 = new THREE.Vector3(), n2 = new THREE.Vector3(), n3 = new THREE.Vector3(), n4 = new THREE.Vector3(), + center1 = new THREE.Vector3(), center2 = new THREE.Vector3(); + + for (var side=0;side<2;++side) { + if ((side > 0) && (shape.fRmin <= 0)) break; + var tube = (side > 0) ? shape.fRmin : shape.fRmax, + d1 = 1 - side, d2 = 1 - d1, ns = side>0 ? -1 : 1; + + for (var t=0;t0) ? 0 : 1, d2 = 1 - d1, + skip = (shape.fRmin) > 0 ? 0 : 1, + nsign = t>0 ? 1 : -1; + for (var n=0;n 0) hasrmin = true; + + var phi0 = thetaStart*Math.PI/180, dphi = thetaLength/radiusSegments*Math.PI/180; + + // calculate all sin/cos tables in advance + var _sin = new Float32Array(radiusSegments+1), _cos = new Float32Array(radiusSegments+1); + for (var seg=0;seg<=radiusSegments;++seg) { + _cos[seg] = Math.cos(phi0+seg*dphi); + _sin[seg] = Math.sin(phi0+seg*dphi); + } + + var indxs = [[],[]], pnts = null, edges = null; // remember indexes for each layer + var layerVerticies = radiusSegments; // how many verticies in one layer + + if (thetaLength !== 360) { + pnts = []; // coordinate of point on cut edge (x,z) + edges = []; // number of layer for that points + layerVerticies+=1; // one need one more vertice + } + + var a,b,c,d,e; // used for face swapping + + for (var side = 0; side < 2; ++side) { + + var rside = (side === 0) ? 'fRmax' : 'fRmin'; + var prev_indx = geometry.vertices.length; + + for (var layer=0; layer < shape.fNz; ++layer) { + + indxs[side][layer] = geometry.vertices.length; + + // first create points for the layer + var layerz = shape.fZ[layer], rad = shape[rside][layer]; + + if ((layer > 0) && (layer < shape.fNz-1)) { + if (((shape.fZ[layer-1] === layerz) && (shape[rside][layer-1] === rad)) || + ((shape[rside][layer+1] === rad) && (shape[rside][layer-1] === rad))) { + + // same Z and R as before - ignore + // or same R before and after + indxs[side][layer] = indxs[side][layer-1]; + // if (len) len[side][layer] = len[side][layer-1]; + continue; + } + } + + if (rad <= 0.) rad = 0.000001; + + var curr_indx = geometry.vertices.length; + + // create vertices for the layer (if rmin===0, only central point is included + if ((side===0) || hasrmin) + for (var seg=0; seg < layerVerticies; ++seg) + geometry.vertices.push( new THREE.Vector3( rad*_cos[seg], rad*_sin[seg], layerz )); + else + geometry.vertices.push( new THREE.Vector3( 0, 0, layerz )); + + if (pnts !== null) { + if (side === 0) { + pnts.push(new THREE.Vector2(rad, layerz)); + edges.push(curr_indx); + } else + if (rad < shape.fRmax[layer]) { + pnts.unshift(new THREE.Vector2(rad, layerz)); + edges.unshift(curr_indx); + } + } + + if ((layer>0) && ((side===0) || hasrmin)) // create faces + for (var seg=0;seg < radiusSegments;++seg) { + var seg1 = (seg + 1) % layerVerticies; + geometry.faces.push( new THREE.Face3( prev_indx + seg, (side === 0) ? (prev_indx + seg1) : (curr_indx + seg) , curr_indx + seg1, null, color, 0 ) ); + geometry.faces.push( new THREE.Face3( prev_indx + seg, curr_indx + seg1, (side === 0) ? (curr_indx + seg) : prev_indx + seg1, null, color, 0 )); + } + + prev_indx = curr_indx; + } + } + + // add faces for top and bottom side + for (var layer = 0; layer < shape.fNz; layer+= (shape.fNz-1)) { + if (shape.fRmin[layer] >= shape.fRmax[layer]) continue; + var inside = indxs[1][layer], outside = indxs[0][layer]; + for (var seg=0; seg < radiusSegments; ++seg) { + var seg1 = (seg + 1) % layerVerticies; + if (hasrmin) { + geometry.faces.push( new THREE.Face3( outside + seg, (layer===0) ? (inside + seg) : (outside + seg1), inside + seg1, null, color, 0 ) ); + geometry.faces.push( new THREE.Face3( outside + seg, inside + seg1, (layer===0) ? (outside + seg1) : (inside + seg), null, color, 0 )); + } else + if (layer==0) { + geometry.faces.push( new THREE.Face3( outside + seg, inside, outside + seg1, null, color, 0 )); + } else { + geometry.faces.push( new THREE.Face3( outside + seg1, inside, outside + seg, null, color, 0 )); + } + } + } + + if (pnts!==null) { + var faces = []; + if (pnts.length === shape.fNz * 2) { + // special case - all layers are there, create faces ourself + for (var layer = shape.fNz-1; layer>0; --layer) { + if (shape.fZ[layer] === shape.fZ[layer-1]) continue; + var right = 2*shape.fNz - 1 - layer; + faces.push([right, layer - 1, layer]); + faces.push([right, right + 1, layer-1]); + } + + } else { + // let three.js calculate our faces + faces = THREE.ShapeUtils.triangulateShape(pnts, []); + } + + for (var i = 0; i < faces.length; ++i) { + var f = faces[i]; + geometry.faces.push( new THREE.Face3( edges[f[0]], edges[f[1]], edges[f[2]], null, color, 0) ); + } + for (var i = 0; i < faces.length; ++i) { + var f = faces[i]; + geometry.faces.push( new THREE.Face3( edges[f[0]] + radiusSegments, edges[f[2]] + radiusSegments, edges[f[1]] + radiusSegments, null, color, 0) ); + } + } + + geometry.computeFaceNormals(); + + return geometry; + } + + + /** @memberOf JSROOT.GEO */ + JSROOT.GEO.createPolygonBuffer = function( shape, faces_limit ) { + var thetaStart = shape.fPhi1, + thetaLength = shape.fDphi, + radiusSegments = 60; + + if ( shape._typename == "TGeoPgon" ) + radiusSegments = shape.fNedges; + else + radiusSegments = Math.max(5, Math.round(thetaLength/JSROOT.GEO.GradPerSegm)); + + var usage = new Int16Array(2*shape.fNz), numusedlayers = 0, hasrmin = false; + + for (var layer=0; layer < shape.fNz; ++layer) + if (shape.fRmin[layer] > 0) hasrmin = true; + + // return very rought estimation, number of faces may be much less + if (faces_limit < 0) return (hasrmin ? 4 : 2) * radiusSegments * (shape.fNz-1); + + // coordinate of point on cut edge (x,z) + var pnts = (thetaLength === 360) ? null : []; + + // first analyse levels - if we need to create all of them + for (var side = 0; side < 2; ++side) { + var rside = (side === 0) ? 'fRmax' : 'fRmin'; + + for (var layer=0; layer < shape.fNz; ++layer) { + + // first create points for the layer + var layerz = shape.fZ[layer], rad = shape[rside][layer]; + + usage[layer*2+side] = 0; + + if ((layer > 0) && (layer < shape.fNz-1)) + if (((shape.fZ[layer-1] === layerz) && (shape[rside][layer-1] === rad)) || + ((shape[rside][layer+1] === rad) && (shape[rside][layer-1] === rad))) { + + // same Z and R as before - ignore + // or same R before and after + + continue; + } + + if ((layer>0) && ((side === 0) || hasrmin)) { + usage[layer*2+side] = 1; + numusedlayers++; + } + + if (pnts !== null) { + if (side === 0) { + pnts.push(new THREE.Vector2(rad, layerz)); + } else + if (rad < shape.fRmax[layer]) { + pnts.unshift(new THREE.Vector2(rad, layerz)); + } + } + } + } + + var numfaces = numusedlayers*radiusSegments*2; + if (shape.fRmin[0] !== shape.fRmax[0]) numfaces += radiusSegments * (hasrmin ? 2 : 1); + if (shape.fRmin[shape.fNz-1] !== shape.fRmax[shape.fNz-1]) numfaces += radiusSegments * (hasrmin ? 2 : 1); + + var cut_faces = null; + + if (pnts!==null) { + if (pnts.length === shape.fNz * 2) { + // special case - all layers are there, create faces ourself + cut_faces = []; + for (var layer = shape.fNz-1; layer>0; --layer) { + if (shape.fZ[layer] === shape.fZ[layer-1]) continue; + var right = 2*shape.fNz - 1 - layer; + cut_faces.push([right, layer - 1, layer]); + cut_faces.push([right, right + 1, layer-1]); + } + + } else { + // let three.js calculate our faces + console.log('trinagulate ' + shape.fName); + cut_faces = THREE.ShapeUtils.triangulateShape(pnts, []); + console.log('trinagulate done ' + cut_faces.length); + } + numfaces += cut_faces.length*2; + } + + var phi0 = thetaStart*Math.PI/180, dphi = thetaLength/radiusSegments*Math.PI/180; + + // calculate all sin/cos tables in advance + var _sin = new Float32Array(radiusSegments+1), + _cos = new Float32Array(radiusSegments+1); + for (var seg=0;seg<=radiusSegments;++seg) { + _cos[seg] = Math.cos(phi0+seg*dphi); + _sin[seg] = Math.sin(phi0+seg*dphi); + } + + var creator = faces_limit ? new JSROOT.GEO.PolygonsCreator : new JSROOT.GEO.GeometryCreator(numfaces); + + // var creator = new JSROOT.GEO.GeometryCreator(numfaces); + + // add sides + for (var side = 0; side < 2; ++side) { + var rside = (side === 0) ? 'fRmax' : 'fRmin', + z1 = shape.fZ[0], r1 = shape[rside][0], + d1 = 1 - side, d2 = side; + + for (var layer=0; layer < shape.fNz; ++layer) { + + if (usage[layer*2+side] === 0) continue; + + var z2 = shape.fZ[layer], r2 = shape[rside][layer], + nxy = 1, nz = 0; + + if ((r2 !== r1)) { + var angle = Math.atan2((r2-r1), (z2-z1)); + nxy = Math.cos(angle); + nz = Math.sin(angle); + } + + if (side>0) { nxy*=-1; nz*=-1; } + + for (var seg=0;seg < radiusSegments;++seg) { + creator.AddFace4(r1 * _cos[seg+d1], r1 * _sin[seg+d1], z1, + r2 * _cos[seg+d1], r2 * _sin[seg+d1], z2, + r2 * _cos[seg+d2], r2 * _sin[seg+d2], z2, + r1 * _cos[seg+d2], r1 * _sin[seg+d2], z1); + creator.SetNormal_12_34(nxy*_cos[seg+d1], nxy*_sin[seg+d1], nz, nxy*_cos[seg+d2], nxy*_sin[seg+d2], nz); + } + + z1 = z2; r1 = r2; + } + } + + // add top/bottom + for (var layer=0; layer < shape.fNz; layer += (shape.fNz-1)) { + + var rmin = shape.fRmin[layer], rmax = shape.fRmax[layer]; + + if (rmin === rmax) continue; + + var layerz = shape.fZ[layer], + d1 = (layer===0) ? 1 : 0, d2 = 1 - d1, + normalz = (layer===0) ? -1: 1; + + if (!hasrmin && !cut_faces) creator.StartPolygon(layer>0); + + for (var seg=0;seg < radiusSegments;++seg) { + creator.AddFace4(rmin * _cos[seg+d1], rmin * _sin[seg+d1], layerz, + rmax * _cos[seg+d1], rmax * _sin[seg+d1], layerz, + rmax * _cos[seg+d2], rmax * _sin[seg+d2], layerz, + rmin * _cos[seg+d2], rmin * _sin[seg+d2], layerz, + hasrmin ? 0 : 2); + creator.SetNormal(0, 0, normalz); + } + + creator.StopPolygon(); + } + + if (cut_faces) + for (var seg = 0; seg <= radiusSegments; seg += radiusSegments) { + var d1 = (seg === 0) ? 1 : 2, d2 = 3 - d1; + for (var n=0;n0) // create faces for sides + for (var vert = 0; vert < shape.fNvert; ++vert) { + var vert1 = (vert + 1) % shape.fNvert; + geometry.faces.push( new THREE.Face3( prev + vert, curr + vert, curr + vert1, null, fcolor, 0 ) ); + geometry.faces.push( new THREE.Face3( prev + vert, curr + vert1, prev + vert1, null, fcolor, 0 )); + } + } + + // now try to make shape - use standard THREE.js utils + + var pnts = []; + for (var vert = 0; vert < shape.fNvert; ++vert) + pnts.push( new THREE.Vector2(shape.fX[vert], shape.fY[vert])); + + var faces = THREE.ShapeUtils.triangulateShape(pnts , []); + + for (var i = 0; i < faces.length; ++i) { + face = faces[ i ]; + geometry.faces.push( new THREE.Face3( face[1], face[0], face[2], null, fcolor, 0) ); + geometry.faces.push( new THREE.Face3( face[0] + curr, face[1] + curr, face[2] + curr, null, fcolor, 0) ); + } + + geometry.computeFaceNormals(); + + return geometry; + } + + + /** @memberOf JSROOT.GEO */ + JSROOT.GEO.createXtruBuffer = function( shape, faces_limit ) { + var nfaces = (shape.fNz-1) * shape.fNvert * 2; + + if (faces_limit < 0) return nfaces + shape.fNvert*3; + + // create points + var pnts = []; + for (var vert = 0; vert < shape.fNvert; ++vert) + pnts.push(new THREE.Vector2(shape.fX[vert], shape.fY[vert])); + + var faces = THREE.ShapeUtils.triangulateShape(pnts , []); + if (faces.length < pnts.length-2) { + JSROOT.GEO.warn('Problem with XTRU shape ' +shape.fName + ' with ' + pnts.length + ' vertices'); + faces = []; + } else { + nfaces += faces.length * 2; + } + + var creator = faces_limit ? new JSROOT.GEO.PolygonsCreator : new JSROOT.GEO.GeometryCreator(nfaces); + + for (var layer = 0; layer < shape.fNz-1; ++layer) { + var z1 = shape.fZ[layer], scale1 = shape.fScale[layer], + z2 = shape.fZ[layer+1], scale2 = shape.fScale[layer+1]; + + for (var vert1 = 0; vert1 < shape.fNvert; ++vert1) { + var vert2 = (vert1+1) % shape.fNvert; + creator.AddFace4(scale1 * shape.fX[vert1], scale1 * shape.fY[vert1], z1, + scale2 * shape.fX[vert1], scale2 * shape.fY[vert1], z2, + scale2 * shape.fX[vert2], scale2 * shape.fY[vert2], z2, + scale1 * shape.fX[vert2], scale1 * shape.fY[vert2], z1); + creator.CalcNormal(); + } + } + + for (layer = 0; layer <= shape.fNz-1; layer+=(shape.fNz-1)) { + var z = shape.fZ[layer], scale = shape.fScale[layer]; + + for (var n=0;n 0) { + var fact = 2 * (radiusSegments+1) * (heightSegments+1) / faces_limit; + if (fact > 1.) { + radiusSegments = Math.round(radiusSegments/Math.sqrt(fact)); + heightSegments = Math.round(heightSegments/Math.sqrt(fact)); + } + } + + // calculate all sin/cos tables in advance + var _sin = new Float32Array(radiusSegments), _cos = new Float32Array(radiusSegments); + for (var seg=0;seg= 0) { + if (shape.fB > zmin) zmin = shape.fB; + } else { + if (shape.fB < zmax) zmax = shape.fB; + } + + var ttmin = Math.atan2(zmin, rmin), ttmax = Math.atan2(zmax, rmax); + + var prev_indx = 0, prev_radius = 0; + + for (var layer = 0; layer <= heightSegments + 1; ++layer) { + var layerz = zmax, radius = 0; + + if ((layer === heightSegments + 1) && (prev_radius === 0)) break; + + switch (layer) { + case 0: layerz = zmin; radius = rmin; break; + case heightSegments: layerz = zmax; radius = rmax; break; + case heightSegments + 1: layerz = zmax; radius = 0; break; + default: { + var tt = Math.tan(ttmin + (ttmax-ttmin) * layer / heightSegments); + var delta = tt*tt - 4*shape.fA*shape.fB; // should be always positive (a*b<0) + radius = 0.5*(tt+Math.sqrt(delta))/shape.fA; + if (radius < 1e-6) radius = 0; + layerz = radius*tt; + } + } + + var curr_indx = geometry.vertices.length; + + if (radius === 0) { + geometry.vertices.push( new THREE.Vector3( 0, 0, layerz )); + } else { + for (var seg=0; seg0) { + for (var seg=0; seg 0) { + var fact = 2*radiusSegments*(heightSegments+1) / faces_limit; + if (fact > 1.) { + radiusSegments = Math.max(5, Math.floor(radiusSegments/Math.sqrt(fact))); + heightSegments = Math.max(5, Math.floor(heightSegments/Math.sqrt(fact))); + } + } + + var zmin = -shape.fDZ, zmax = shape.fDZ, rmin = shape.fRlo, rmax = shape.fRhi; + + // if no radius at -z, find intersection + if (shape.fA >= 0) { + if (shape.fB > zmin) zmin = shape.fB; + } else { + if (shape.fB < zmax) zmax = shape.fB; + } + + var ttmin = Math.atan2(zmin, rmin), ttmax = Math.atan2(zmax, rmax); + + var numfaces = (heightSegments+1)*radiusSegments*2; + if (rmin===0) numfaces -= radiusSegments*2; // complete layer + if (rmax===0) numfaces -= radiusSegments*2; // complete layer + + if (faces_limit < 0) return numfaces; + + // calculate all sin/cos tables in advance + var _sin = new Float32Array(radiusSegments+1), + _cos = new Float32Array(radiusSegments+1); + for (var seg=0;seg<=radiusSegments;++seg) { + _cos[seg] = Math.cos(seg/radiusSegments*2*Math.PI); + _sin[seg] = Math.sin(seg/radiusSegments*2*Math.PI); + } + + var creator = faces_limit ? new JSROOT.GEO.PolygonsCreator : new JSROOT.GEO.GeometryCreator(numfaces); + + var lastz = zmin, lastr = 0, lastnxy = 0, lastnz = -1; + + for (var layer = 0; layer <= heightSegments + 1; ++layer) { + + var layerz = 0, radius = 0, nxy = 0, nz = -1; + + if ((layer === 0) && (rmin===0)) continue; + + if ((layer === heightSegments + 1) && (lastr === 0)) break; + + switch (layer) { + case 0: layerz = zmin; radius = rmin; break; + case heightSegments: layerz = zmax; radius = rmax; break; + case heightSegments + 1: layerz = zmax; radius = 0; break; + default: { + var tt = Math.tan(ttmin + (ttmax-ttmin) * layer / heightSegments); + var delta = tt*tt - 4*shape.fA*shape.fB; // should be always positive (a*b<0) + radius = 0.5*(tt+Math.sqrt(delta))/shape.fA; + if (radius < 1e-6) radius = 0; + layerz = radius*tt; + } + } + + nxy = shape.fA * radius; + nz = (shape.fA > 0) ? -1 : 1; + + var skip = 0; + if (lastr === 0) skip = 1; else + if (radius === 0) skip = 2; + + for (var seg=0; seg 0) { + var fact = ((shape.fRmin <= 0) ? 2 : 4) * (radiusSegments+1) * (heightSegments+2) / faces_limit; + if (fact > 1.) { + radiusSegments = Math.round(radiusSegments/Math.sqrt(fact)); + heightSegments = Math.round(heightSegments/Math.sqrt(fact)); + } + } + + // calculate all sin/cos tables in advance + var _sin = new Float32Array(radiusSegments), _cos = new Float32Array(radiusSegments); + for (var seg=0;seg0) { + for (var seg=0; seg 0) ? 4 : 2); + + if (faces_limit < 0) return numfaces; + + if ((faces_limit > 0) && (faces_limit > numfaces)) { + radiusSegments = Math.max(4, Math.floor(radiusSegments/Math.sqrt(numfaces/faces_limit))); + heightSegments = Math.max(4, Math.floor(heightSegments/Math.sqrt(numfaces/faces_limit))); + numfaces = radiusSegments * (heightSegments + 1) * ((shape.fRmin > 0) ? 4 : 2); + } + + // calculate all sin/cos tables in advance + var _sin = new Float32Array(radiusSegments+1), _cos = new Float32Array(radiusSegments+1); + for (var seg=0;seg<=radiusSegments;++seg) { + _cos[seg] = Math.cos(seg/radiusSegments*2*Math.PI); + _sin[seg] = Math.sin(seg/radiusSegments*2*Math.PI); + } + + var creator = faces_limit ? new JSROOT.GEO.PolygonsCreator : new JSROOT.GEO.GeometryCreator(numfaces); + + // in-out side + for (var side=0;side<2;++side) { + if ((side > 0) && (shape.fRmin <= 0)) break; + + var r0 = (side > 0) ? shape.fRmin : shape.fRmax, + tsq = (side > 0) ? shape.fTinsq : shape.fToutsq, + d1 = 1- side, d2 = 1 - d1; + + // vertical layers + for (var layer=0;layer 0) ? Math.sqrt(shape.fRmin*shape.fRmin + shape.fTinsq*z*z) : 0, + skip = (shape.fRmin > 0) ? 0 : 1, + d1 = 1 - layer, d2 = 1 - d1; + for (var seg=0; seg 0 return list of ThreeBSP polygons (used only for composite shapes) + * */ + JSROOT.GEO.createGeometry = function( shape, limit ) { + if (limit === undefined) limit = 0; + + try { + switch (shape._typename) { + case "TGeoBBox": return JSROOT.GEO.createCubeBuffer( shape, limit ); + case "TGeoPara": return JSROOT.GEO.createParaBuffer( shape, limit ); + case "TGeoTrd1": + case "TGeoTrd2": return JSROOT.GEO.createTrapezoidBuffer( shape, limit ); + case "TGeoArb8": + case "TGeoTrap": + case "TGeoGtra": return JSROOT.GEO.createArb8Buffer( shape, limit ); + case "TGeoSphere": return JSROOT.GEO.createSphereBuffer( shape , limit ); + case "TGeoCone": + case "TGeoConeSeg": + case "TGeoTube": + case "TGeoTubeSeg": + case "TGeoCtub": return JSROOT.GEO.createTubeBuffer( shape, limit ); + case "TGeoEltu": return JSROOT.GEO.createEltuBuffer( shape, limit ); + case "TGeoTorus": return JSROOT.GEO.createTorusBuffer( shape, limit ); + case "TGeoPcon": + case "TGeoPgon": return JSROOT.GEO.createPolygonBuffer( shape, limit ); + case "TGeoXtru": return JSROOT.GEO.createXtruBuffer( shape, limit ); + case "TGeoParaboloid": return JSROOT.GEO.createParaboloidBuffer( shape, limit ); + case "TGeoHype": return JSROOT.GEO.createHypeBuffer( shape, limit ); + case "TGeoCompositeShape": return JSROOT.GEO.createComposite( shape, limit ); + case "TGeoShapeAssembly": break; + } + } catch(e) { + var place = ""; + if (e.stack !== undefined) { + place = e.stack.split("\n")[0]; + if (place.indexOf(e.message) >= 0) place = e.stack.split("\n")[1]; + else place = " at: " + place; + } + JSROOT.GEO.warn(shape._typename + " err: " + e.message + place); + + } + + + return limit < 0 ? 0 : null; + } + + /** @memberOf JSROOT.GEO */ + JSROOT.GEO.CreateProjectionMatrix = function(camera) { + var cameraProjectionMatrix = new THREE.Matrix4(); + + camera.updateMatrixWorld(); + camera.matrixWorldInverse.getInverse( camera.matrixWorld ); + cameraProjectionMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse); + + return cameraProjectionMatrix; + } + + /** @memberOf JSROOT.GEO */ + JSROOT.GEO.CreateFrustum = function(source) { + if (!source) return null; + + if (source instanceof THREE.PerspectiveCamera) + source = JSROOT.GEO.CreateProjectionMatrix(source); + + var frustum = new THREE.Frustum(); + frustum.setFromMatrix(source); + + frustum.corners = new Float32Array([ + 1, 1, 1, + 1, 1, -1, + 1, -1, 1, + 1, -1, -1, + -1, 1, 1, + -1, 1, -1, + -1, -1, 1, + -1, -1, -1, + 0, 0, 0 // also check center of the shape + ]); + + frustum.test = new THREE.Vector3(0,0,0); + + frustum.CheckShape = function(matrix, shape) { + var pnt = this.test, len = this.corners.length, corners = this.corners, i; + + for (i = 0; i < len; i+=3) { + pnt.x = corners[i] * shape.fDX; + pnt.y = corners[i+1] * shape.fDY; + pnt.z = corners[i+2] * shape.fDZ; + if (this.containsPoint(pnt.applyMatrix4(matrix))) return true; + } + + return false; + } + + frustum.CheckBox = function(box) { + var pnt = this.test, cnt = 0; + pnt.set(box.min.x, box.min.y, box.min.z); + if (this.containsPoint(pnt)) cnt++; + pnt.set(box.min.x, box.min.y, box.max.z); + if (this.containsPoint(pnt)) cnt++; + pnt.set(box.min.x, box.max.y, box.min.z); + if (this.containsPoint(pnt)) cnt++; + pnt.set(box.min.x, box.max.y, box.max.z); + if (this.containsPoint(pnt)) cnt++; + pnt.set(box.max.x, box.max.y, box.max.z); + if (this.containsPoint(pnt)) cnt++; + pnt.set(box.max.x, box.min.y, box.max.z); + if (this.containsPoint(pnt)) cnt++; + pnt.set(box.max.x, box.max.y, box.min.z); + if (this.containsPoint(pnt)) cnt++; + pnt.set(box.max.x, box.max.y, box.max.z); + if (this.containsPoint(pnt)) cnt++; + return cnt>5; // only if 6 edges and more are seen, we think that box is fully visisble + } + + return frustum; + } + + /** @memberOf JSROOT.GEO */ + JSROOT.GEO.VisibleByCamera = function(camera, matrix, shape) { + var frustum = new THREE.Frustum(); + var cameraProjectionMatrix = new THREE.Matrix4(); + + camera.updateMatrixWorld(); + camera.matrixWorldInverse.getInverse( camera.matrixWorld ); + cameraProjectionMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse); + frustum.setFromMatrix( cameraProjectionMatrix ); + + var corners = [ + new THREE.Vector3( shape.fDX/2.0, shape.fDY/2.0, shape.fDZ/2.0 ), + new THREE.Vector3( shape.fDX/2.0, shape.fDY/2.0, -shape.fDZ/2.0 ), + new THREE.Vector3( shape.fDX/2.0, -shape.fDY/2.0, shape.fDZ/2.0 ), + new THREE.Vector3( shape.fDX/2.0, -shape.fDY/2.0, -shape.fDZ/2.0 ), + new THREE.Vector3( -shape.fDX/2.0, shape.fDY/2.0, shape.fDZ/2.0 ), + new THREE.Vector3( -shape.fDX/2.0, shape.fDY/2.0, -shape.fDZ/2.0 ), + new THREE.Vector3( -shape.fDX/2.0, -shape.fDY/2.0, shape.fDZ/2.0 ), + new THREE.Vector3( -shape.fDX/2.0, -shape.fDY/2.0, -shape.fDZ/2.0 ) + ]; + for (var i = 0; i < corners.length; i++) { + if (frustum.containsPoint(corners[i].applyMatrix4(matrix))) return true; + } + + return false; + } + + /** @memberOf JSROOT.GEO */ + JSROOT.GEO.numGeometryFaces = function(geom) { + if (!geom) return 0; + + if (geom instanceof ThreeBSP) + return geom.tree.numPolygons(); + + if (geom.type == 'BufferGeometry') { + var attr = geom.getAttribute('position'); + return attr ? attr.count / 3 : 0; + } + + // special array of polygons + if (geom && geom.polygons) return geom.polygons.length; + + return geom.faces.length; + } + + /** @memberOf JSROOT.GEO */ + JSROOT.GEO.numGeometryVertices = function(geom) { + if (!geom) return 0; + + if (geom instanceof ThreeBSP) + return geom.tree.numPolygons() * 3; + + if (geom.type == 'BufferGeometry') { + var attr = geom.getAttribute('position'); + return attr ? attr.count : 0; + } + + if (geom && geom.polygons) return geom.polygons.length * 4; + + return geom.vertices.length; + } + + // ==================================================================== + + // class for working with cloned nodes + + JSROOT.GEO.ClonedNodes = function(obj, clones) { + this.toplevel = true; // indicate if object creates top-level structure with Nodes and Volumes folder + + if (obj) { + if (obj._geoh) this.toplevel = false; + this.CreateClones(obj); + } else + if (clones) this.nodes = clones; + } + + JSROOT.GEO.ClonedNodes.prototype.GetNodeShape = function(indx) { + if (!this.origin || !this.nodes) return null; + var obj = this.origin[indx], clone = this.nodes[indx]; + if (!obj || !clone) return null; + if (clone.kind === 0) { + if (obj.fVolume) return obj.fVolume.fShape; + } else { + return obj.fShape; + } + return null; + } + + JSROOT.GEO.ClonedNodes.prototype.CreateClones = function(obj, sublevel) { + if (!sublevel) { + this.origin = []; + sublevel = 1; + } + + var kind = JSROOT.GEO.NodeKind(obj); + if ((kind < 0) || ('_refid' in obj)) return; + + obj._refid = this.origin.length; + this.origin.push(obj); + + var chlds = null; + if (kind === 0) { + chlds = (obj.fVolume && obj.fVolume.fNodes) ? obj.fVolume.fNodes.arr : null; + } else { + chlds = obj.fElements ? obj.fElements.arr : null; + } + + if (chlds !== null) + for (var i = 0; i < chlds.length; ++i) + this.CreateClones(chlds[i], sublevel+1); + + if (sublevel > 1) return; + + this.nodes = []; + + var sortarr = []; + + // first create nodes objects + for (var n=0; n 0) ? arg.matrices[arg.last-1] : new THREE.Matrix4(); + if (node.matrix) { + arg.matrices[arg.last] = arg.mpool[arg.last].fromArray(prnt.elements); + arg.matrices[arg.last].multiply(arg.mpool[arg.last+1].fromArray(node.matrix)); + } else { + arg.matrices[arg.last] = prnt; + } + } + + if (node.vis && (vislvl>=0)) { + if (!arg.func || arg.func(node)) res++; + } + + arg.counter++; + + if ((node.depth !== undefined) && (vislvl > node.depth)) vislvl = node.depth; + + if (arg.last > arg.stack.length - 2) + throw 'stack capacity is not enough ' + arg.stack.length; + + if (node.chlds && (node.numvischld > 0)) { + var currid = arg.counter, numvischld = 0; + arg.last++; + for (var i = 0; i < node.chlds.length; ++i) { + arg.nodeid = node.chlds[i]; + arg.stack[arg.last] = i; // in the stack one store index of child, it is path in the hierarchy + numvischld += this.ScanVisible(arg, vislvl-1); + } + arg.last--; + res += numvischld; + if (numvischld === 0) { + node.numvischld = 0; + node.idshift = arg.counter - currid; + } + } else { + arg.counter += node.idshift; + } + + if (arg.last === 0) { + delete arg.last; + delete arg.stack; + delete arg.CopyStack; + delete arg.counter; + delete arg.matrices; + delete arg.mpool; + delete arg.getmatrix; + } + + return res; + } + + JSROOT.GEO.ClonedNodes.prototype.ResolveStack = function(stack, withmatrix) { + + var res = { id: 0, obj: null, node: this.nodes[0], name: "Nodes" }; + + if (!this.toplevel || (this.nodes.length === 1) || (res.node.kind === 1)) res.name = ""; + + if (withmatrix) { + res.matrix = new THREE.Matrix4(); + if (res.node.matrix) res.matrix.fromArray(res.node.matrix); + } + + if (this.origin) res.obj = this.origin[0]; + + if (stack) + for(var lvl=0;lvl0) res.name += "/"; + res.name += res.obj.fName; + } + } + + if (withmatrix && res.node.matrix) + res.matrix.multiply(new THREE.Matrix4().fromArray(res.node.matrix)); + } + + return res; + } + + JSROOT.GEO.ClonedNodes.prototype.FindStackByName = function(fullname) { + if (!this.origin) return null; + + var names = fullname.split('/'); + + var currid = 0, stack = []; + + for (var n=0;n 0) ? stack[lvl-1] : 0; + // extract current node + if (lvl>0) node = this.nodes[node.chlds[nchld]]; + + var obj3d = undefined; + + if (three_prnt.children) + for (var i=0;i maxnumfaces) { + + var bignumfaces = maxnumfaces * (frustum ? 0.8 : 1.0); + + // define minimal volume, which always to shown + var boundary = this.GetVolumeBoundary(arg.viscnt, bignumfaces, bignumfaces/100); + + minVol = boundary.min; + maxVol = boundary.max; + + if (frustum) { + arg.domatrix = true; + arg.frustum = frustum; + arg.totalcam = 0; + arg.func = function(node) { + if (node.vol <= minVol) // only small volumes are interesting + if (this.frustum.CheckShape(this.getmatrix(), node)) { + this.viscnt[node.id]++; + this.totalcam += node.nfaces; + } + + return true; + } + + for (var n=0;n maxnumfaces*0.2) + camVol = this.GetVolumeBoundary(arg.viscnt, maxnumfaces*0.2, maxnumfaces*0.2/100).min; + else + camVol = 0; + + camFact = maxVol / ((camVol>0) ? (camVol>0) : minVol); + + // console.log('Limit for camera ' + camVol + ' faces in camera view ' + arg.totalcam); + } + } + + arg.items = []; + + arg.func = function(node) { + if (node.vol > minVol) { + this.items.push(this.CopyStack()); + } else + if ((camVol >= 0) && (node.vol > camVol)) + if (this.frustum.CheckShape(this.getmatrix(), node)) { + this.items.push(this.CopyStack(camFact)); + } + return true; + } + + this.ScanVisible(arg); + + return { lst: arg.items, complete: minVol === 0 }; + } + + JSROOT.GEO.ClonedNodes.prototype.MergeVisibles = function(current, prev) { + // merge list of drawn objects + // in current list we should mark if object already exists + // from previous list we should collect objects which are not there + + var indx2 = 0, del = []; + for (var indx1=0; (indx1entry.shape.factor)) + entry.shape.factor = entry.factor; + } + + // now sort shapes in volume decrease order + shapes.sort(function(a,b) { return b.vol*b.factor - a.vol*a.factor; }) + + // now set new shape ids according to the sorted order and delete temporary field + for (var n=0;n= limit) { + res.done = true; + } else + if ((created > 0.01*lst.length) && (timelimit!==undefined)) { + var tm2 = new Date().getTime(); + if (tm2-tm1 > timelimit) return res; + } + } + + res.done = true; + + return res; + } + + return JSROOT; + +})); + diff --git a/visualisations/JsRoot460/scripts/JSRootGeoBase.min.js b/visualisations/JsRoot460/scripts/JSRootGeoBase.min.js new file mode 100644 index 0000000..4126f0c --- /dev/null +++ b/visualisations/JsRoot460/scripts/JSRootGeoBase.min.js @@ -0,0 +1 @@ +(function(a){if(typeof define==="function"&&define.amd){define(["JSRootCore","threejs","ThreeCSG"],a)}else{if(typeof JSROOT=="undefined"){throw new Error("JSROOT is not defined","JSRootGeoBase.js")}if(typeof THREE=="undefined"){throw new Error("THREE is not defined","JSRootGeoBase.js")}a(JSROOT)}}(function(a){a.GEO={GradPerSegm:6,CompressComp:true};a.GEO.BITS={kVisOverride:a.BIT(0),kVisNone:a.BIT(1),kVisThis:a.BIT(2),kVisDaughters:a.BIT(3),kVisOneLevel:a.BIT(4),kVisStreamed:a.BIT(5),kVisTouched:a.BIT(6),kVisOnScreen:a.BIT(7),kVisContainers:a.BIT(12),kVisOnly:a.BIT(13),kVisBranch:a.BIT(14),kVisRaytrace:a.BIT(15)};a.GEO.TestBit=function(c,d){var b=c.fGeoAtt;return b===undefined?false:((b&d)!==0)};a.GEO.SetBit=function(b,d,c){if(b.fGeoAtt===undefined){return}b.fGeoAtt=c?(b.fGeoAtt|d):(b.fGeoAtt&~d)};a.GEO.ToggleBit=function(b,c){if(b.fGeoAtt!==undefined){b.fGeoAtt=b.fGeoAtt^(c&16777215)}};a.GEO.warn=function(b){if(a.GEO._warn_msgs===undefined){a.GEO._warn_msgs={}}if(a.GEO._warn_msgs[b]!==undefined){return}a.GEO._warn_msgs[b]=true;console.warn(b)};a.GEO.NodeKind=function(b){if((b===undefined)||(b===null)||(typeof b!=="object")){return -1}return("fShape" in b)&&("fTrans" in b)?1:0};a.GEO.getNodeProperties=function(g,f,e){if(g===1){var b={name:f.fName,nname:f.fName,shape:f.fShape,material:null,chlds:null};if(f.fElements!==null){b.chlds=f.fElements.arr}if(e){var j=false,i=1;if(f.fRGBA[3]<1){j=true;i=f.fRGBA[3]}b.fillcolor=new THREE.Color(f.fRGBA[0],f.fRGBA[1],f.fRGBA[2]);b.material=new THREE.MeshLambertMaterial({transparent:j,opacity:i,wireframe:false,color:b.fillcolor,side:THREE.FrontSide,vertexColors:THREE.NoColors,overdraw:0});b.material.alwaysTransparent=j;b.material.inherentOpacity=i}return b}var h=f.fVolume;var b={name:h.fName,nname:f.fName,volume:f.fVolume,shape:h.fShape,material:null,chlds:null};if(f.fVolume.fNodes!==null){b.chlds=f.fVolume.fNodes.arr}if(e){var j=false,i=1;if((h.fFillColor>1)&&(h.fLineColor==1)){b.fillcolor=a.Painter.root_colors[h.fFillColor]}else{if(h.fLineColor>=0){b.fillcolor=a.Painter.root_colors[h.fLineColor]}}if(h.fMedium&&h.fMedium.fMaterial){var c=h.fMedium.fMaterial.fFillStyle;var d=(c<3000||c>3100)?0:c-3000;if(d>0){j=true;i=(100-d)/100}if(b.fillcolor===undefined){b.fillcolor=a.Painter.root_colors[h.fMedium.fMaterial.fFillColor]}}if(b.fillcolor===undefined){b.fillcolor="lightgrey"}b.material=new THREE.MeshLambertMaterial({transparent:j,opacity:i,wireframe:false,color:b.fillcolor,side:THREE.FrontSide,vertexColors:THREE.NoColors,overdraw:0});b.material.alwaysTransparent=j;b.material.inherentOpacity=i}return b};a.GEO.GeometryCreator=function(b){this.nfaces=b;this.indx=0;this.pos=new Float32Array(b*9);this.norm=new Float32Array(b*9);return this};a.GEO.GeometryCreator.prototype.AddFace3=function(d,l,g,c,k,f,b,i,e){var h=this.indx,j=this.pos;j[h]=d;j[h+1]=l;j[h+2]=g;j[h+3]=c;j[h+4]=k;j[h+5]=f;j[h+6]=b;j[h+7]=i;j[h+8]=e;this.last4=false;this.indx=h+9};a.GEO.GeometryCreator.prototype.StartPolygon=function(){};a.GEO.GeometryCreator.prototype.StopPolygon=function(){};a.GEO.GeometryCreator.prototype.AddFace4=function(d,o,h,c,n,g,b,l,f,p,j,e,k){var i=this.indx,m=this.pos;if(k!==1){m[i]=d;m[i+1]=o;m[i+2]=h;m[i+3]=c;m[i+4]=n;m[i+5]=g;m[i+6]=b;m[i+7]=l;m[i+8]=f;i+=9}if(k!==2){m[i]=d;m[i+1]=o;m[i+2]=h;m[i+3]=b;m[i+4]=l;m[i+5]=f;m[i+6]=p;m[i+7]=j;m[i+8]=e;i+=9}this.last4=(i!==this.indx+9);this.indx=i};a.GEO.GeometryCreator.prototype.SetNormal4=function(c,m,g,p,k,f,o,j,e,n,i,d,l){if(this.last4&&l){return console.error("missmatch between AddFace4 and SetNormal4 calls")}var h=this.indx-(this.last4?18:9),b=this.norm;if(l!==1){b[h]=c;b[h+1]=m;b[h+2]=g;b[h+3]=p;b[h+4]=k;b[h+5]=f;b[h+6]=o;b[h+7]=j;b[h+8]=e;h+=9}if(l!==2){b[h]=c;b[h+1]=m;b[h+2]=g;b[h+3]=o;b[h+4]=j;b[h+5]=e;b[h+6]=n;b[h+7]=i;b[h+8]=d}};a.GEO.GeometryCreator.prototype.RecalcZ=function(d){var e=this.pos,c=this.indx,b=c-(this.last4?18:9);while(b0)?9:18),b=this.norm;if(i!==1){b[f]=c;b[f+1]=e;b[f+2]=g;b[f+3]=c;b[f+4]=e;b[f+5]=g;b[f+6]=d;b[f+7]=h;b[f+8]=j;f+=9}if(i!==2){b[f]=c;b[f+1]=e;b[f+2]=g;b[f+3]=d;b[f+4]=h;b[f+5]=j;b[f+6]=d;b[f+7]=h;b[f+8]=j;f+=9}};a.GEO.GeometryCreator.prototype.Create=function(){if(this.nfaces!==this.indx/9){console.error("Mismatch with created "+this.nfaces+" and filled "+this.indx/9+" number of faces")}var b=new THREE.BufferGeometry();b.addAttribute("position",new THREE.BufferAttribute(this.pos,3));b.addAttribute("normal",new THREE.BufferAttribute(this.norm,3));return b};a.GEO.PolygonsCreator=function(){this.polygons=[]};a.GEO.PolygonsCreator.prototype.StartPolygon=function(b){this.multi=1;this.mnormal=b};a.GEO.PolygonsCreator.prototype.StopPolygon=function(){if(!this.multi){return}this.multi=0;console.error("Polygon should be already closed at this moment")};a.GEO.PolygonsCreator.prototype.AddFace3=function(d,j,g,c,i,f,b,h,e){this.AddFace4(d,j,g,c,i,f,b,h,e,b,h,e,2)};a.GEO.PolygonsCreator.prototype.AddFace4=function(r,e,m,q,d,j,p,c,i,o,b,h,l){if(l===undefined){l=0}this.v1=new ThreeBSP.Vertex(r,e,m,0,0,0);this.v2=(l===1)?null:new ThreeBSP.Vertex(q,d,j,0,0,0);this.v3=new ThreeBSP.Vertex(p,c,i,0,0,0);this.v4=(l===2)?null:new ThreeBSP.Vertex(o,b,h,0,0,0);this.reduce=l;if(this.multi){if(l!==2){console.error("polygon not supported for not-reduced faces")}var k;if(this.multi++===1){k=new ThreeBSP.Polygon;k.vertices.push(this.mnormal?this.v2:this.v3);this.polygons.push(k)}else{k=this.polygons[this.polygons.length-1];var g=this.mnormal?k.vertices[k.vertices.length-1]:k.vertices[0],s=this.mnormal?this.v2:this.v3;if(s.diff(g)>1e-12){console.error("vertex missmatch when building polygon")}}var f=this.mnormal?k.vertices[0]:k.vertices[k.vertices.length-1],n=this.mnormal?this.v3:this.v2;if(n.diff(f)<1e-12){this.multi=0}else{if(this.mnormal){k.vertices.push(this.v3)}else{k.vertices.unshift(this.v2)}}return}var k=new ThreeBSP.Polygon;switch(l){case 0:k.vertices.push(this.v1,this.v2,this.v3,this.v4);break;case 1:k.vertices.push(this.v1,this.v3,this.v4);break;case 2:k.vertices.push(this.v1,this.v2,this.v3);break}this.polygons.push(k)};a.GEO.PolygonsCreator.prototype.SetNormal4=function(b,k,f,n,i,e,m,h,d,l,g,c,j){this.v1.setnormal(b,k,f);if(this.v2){this.v2.setnormal(n,i,e)}this.v3.setnormal(m,h,d);if(this.v4){this.v4.setnormal(l,g,c)}};a.GEO.PolygonsCreator.prototype.SetNormal_12_34=function(e,c,h,g,d,b,f){this.v1.setnormal(e,c,h);if(this.v2){this.v2.setnormal(e,c,h)}this.v3.setnormal(g,d,b);if(this.v4){this.v4.setnormal(g,d,b)}};a.GEO.PolygonsCreator.prototype.CalcNormal=function(){if(!this.cb){this.pA=new THREE.Vector3();this.pB=new THREE.Vector3();this.pC=new THREE.Vector3();this.cb=new THREE.Vector3();this.ab=new THREE.Vector3()}this.pA.set(this.v1.x,this.v1.y,this.v1.z);if(this.reduce!==1){this.pB.set(this.v2.x,this.v2.y,this.v2.z);this.pC.set(this.v3.x,this.v3.y,this.v3.z)}else{this.pB.set(this.v3.x,this.v3.y,this.v3.z);this.pC.set(this.v4.x,this.v4.y,this.v4.z)}this.cb.subVectors(this.pC,this.pB);this.ab.subVectors(this.pA,this.pB);this.cb.cross(this.ab);this.SetNormal(this.cb.x,this.cb.y,this.cb.z)};a.GEO.PolygonsCreator.prototype.SetNormal=function(b,d,c){this.v1.setnormal(b,d,c);if(this.v2){this.v2.setnormal(b,d,c)}this.v3.setnormal(b,d,c);if(this.v4){this.v4.setnormal(b,d,c)}};a.GEO.PolygonsCreator.prototype.RecalcZ=function(b){this.v1.z=b(this.v1.x,this.v1.y,this.v1.z);if(this.v2){this.v2.z=b(this.v2.x,this.v2.y,this.v2.z)}this.v3.z=b(this.v3.x,this.v3.y,this.v3.z);if(this.v4){this.v4.z=b(this.v4.x,this.v4.y,this.v4.z)}};a.GEO.PolygonsCreator.prototype.Create=function(){return{polygons:this.polygons}};a.GEO.createCube=function(c){var e=new THREE.Geometry();e.vertices.push(new THREE.Vector3(c.fDX,c.fDY,c.fDZ));e.vertices.push(new THREE.Vector3(c.fDX,c.fDY,-c.fDZ));e.vertices.push(new THREE.Vector3(c.fDX,-c.fDY,c.fDZ));e.vertices.push(new THREE.Vector3(c.fDX,-c.fDY,-c.fDZ));e.vertices.push(new THREE.Vector3(-c.fDX,c.fDY,-c.fDZ));e.vertices.push(new THREE.Vector3(-c.fDX,c.fDY,c.fDZ));e.vertices.push(new THREE.Vector3(-c.fDX,-c.fDY,-c.fDZ));e.vertices.push(new THREE.Vector3(-c.fDX,-c.fDY,c.fDZ));var h=[0,2,1,2,3,1,4,6,5,6,7,5,4,5,1,5,0,1,7,6,2,6,3,2,5,7,0,7,2,0,1,3,4,3,6,4];var f=[1,0,0,-1,0,0,0,1,0,0,-1,0,0,0,1,0,0,-1];var b=new THREE.Color();var d=null;for(var i=0;i0)?new a.GEO.PolygonsCreator:new a.GEO.GeometryCreator(12);for(var c=0;c=0)||(d.indexOf(u)>=0)||(d.indexOf(t)>=0)){g[h]=g[h+1]=g[h+2]=-1}else{d.push(v,u,t);p[g[h]]++;p[g[h+1]]++;p[g[h+2]]++}}var r=new THREE.Geometry();for(var j=0;j<8;++j){if(p[j]>0){p[j]=r.vertices.length;r.vertices.push(new THREE.Vector3(l[j*3],l[j*3+1],l[j*3+2]))}else{p[j]=-1}}var f=new THREE.Color();for(var j=0;j<36;j+=3){if(g[j]<0){continue}var s=p[g[j]],q=p[g[j+1]],o=p[g[j+2]];r.faces.push(new THREE.Face3(s,q,o,null,f,0))}r.computeFaceNormals();return r};a.GEO.createArb8Buffer=function(e,j){if(j<0){return 12}var i=[e.fXY[0][0],e.fXY[0][1],-e.fDZ,e.fXY[1][0],e.fXY[1][1],-e.fDZ,e.fXY[2][0],e.fXY[2][1],-e.fDZ,e.fXY[3][0],e.fXY[3][1],-e.fDZ,e.fXY[4][0],e.fXY[4][1],e.fDZ,e.fXY[5][0],e.fXY[5][1],e.fDZ,e.fXY[6][0],e.fXY[6][1],e.fDZ,e.fXY[7][0],e.fXY[7][1],e.fDZ];var f=[4,7,6,6,5,4,0,3,7,7,4,0,4,5,1,1,0,4,6,2,1,1,5,6,7,3,2,2,6,7,1,2,3,3,0,1];for(var g=0;g=0)||(A.indexOf(c)>=0)||(A.indexOf(b)>=0)){f[y]=f[y+1]=f[y+2]=-1}else{A.push(d,c,b);z++}}var o=j?new a.GEO.PolygonsCreator:new a.GEO.GeometryCreator(z);for(var v=0;v=0)&&(t>=0)&&j){if(v===0){h=new THREE.Vector3(0,0,1)}else{if(v===30){h=new THREE.Vector3(0,0,-1)}else{var q=a.GEO.GetNormal(i[x],i[x+1],i[x+2],i[w],i[w+1],i[w+2],i[u],i[u+1],i[u+2]);q.normalize();var p=a.GEO.GetNormal(i[t],i[t+1],i[t+2],i[s],i[s+1],i[s+2],i[r],i[r+1],i[r+2]);p.normalize();if(q.distanceToSquared(p)<1e-12){h=q}}}}if(h!==null){o.AddFace4(i[x],i[x+1],i[x+2],i[w],i[w+1],i[w+2],i[u],i[u+1],i[u+2],i[s],i[s+1],i[s+2]);o.SetNormal(h.x,h.y,h.z)}else{if(x>=0){o.AddFace3(i[x],i[x+1],i[x+2],i[w],i[w+1],i[w+2],i[u],i[u+1],i[u+2]);o.CalcNormal()}if(t>=0){o.AddFace3(i[t],i[t+1],i[t+2],i[s],i[s+1],i[s+2],i[r],i[r+1],i[r+2]);o.CalcNormal()}}}return o.Create()};a.GEO.createSphere=function(d,m){var y=d.fRmax,l=d.fRmin,r=d.fPhi1+180,u=d.fPhi2-d.fPhi1,f=d.fTheta1,s=d.fTheta2-d.fTheta1,e=d.fNseg,q=d.fNz;var b=(l<=0);while(r>=360){r-=360}if(m>0){var c=(b?2:4)*e*q/m;if(c>1){e=Math.round(e/Math.sqrt(c));q=Math.round(q/Math.sqrt(c))}}var h=new THREE.SphereGeometry(y,e,q,r*Math.PI/180,u*Math.PI/180,f*Math.PI/180,s*Math.PI/180);h.applyMatrix(new THREE.Matrix4().makeRotationX(Math.PI/2));var g=new THREE.Geometry();var A=new THREE.Color();for(var t=0;t0){var d=(E?2:4)*z*L/t;if(d>1){z=Math.max(4,Math.floor(z/Math.sqrt(d)));L=Math.max(4,Math.floor(L/Math.sqrt(d)))}}var q=z*L*2,y=z*2,f=z*2,w=N===360?0:L*(E?2:4),D=1e-10;if(E){f=y=z}if(t<0){return q*(E?1:2)+y+f+w}var M=new Float32Array(z+1),c=new Float32Array(z+1),K=new Float32Array(L+1),b=new Float32Array(L+1);for(var G=0;G<=L;++G){var i=(J+o/L*G)*Math.PI/180;K[G]=Math.sin(i);b[G]=Math.cos(i)}for(var G=0;G<=z;++G){var O=(p+N/z*G)*Math.PI/180;M[G]=Math.sin(O);c[G]=Math.cos(O)}if(Math.abs(K[0])<=D){q-=z;y=0}if(Math.abs(K[L])<=D){q-=z;f=0}var m=q*(E?1:2)+y+f+w;var l=t?new a.GEO.PolygonsCreator:new a.GEO.GeometryCreator(m);for(var g=0;g<2;++g){if((g===1)&&E){break}var C=B[g],A=(g===0)?1:-1,H=1-g,F=1-H;for(var I=0;I=D){var e=K[g],x=b[g],H=(g===0)?0:1,F=1-H;for(var G=0;G0)||(y>0);if(k){if(z<=0){z=1e-7;a.GEO.warn("zero inner radius1 in tube - not yet supported")}if(y<=0){y=1e-7;a.GEO.warn("zero inner radius1 in tube - not yet supported")}}var j=0,p=360;if((d._typename=="TGeoConeSeg")||(d._typename=="TGeoTubeSeg")||(d._typename=="TGeoCtub")){j=d.fPhi1;p=d.fPhi2-d.fPhi1}var s=Math.round(p/a.GEO.GradPerSegm);if(s<4){s=4}var g=(p<360)?1:0;var o=s+g;var A=j*Math.PI/180,c=p/s*Math.PI/180;var h=new Float32Array(o),m=new Float32Array(o);for(var x=0;x0)||(d[1]>0);var j=0,q=360;if((f._typename=="TGeoConeSeg")||(f._typename=="TGeoTubeSeg")||(f._typename=="TGeoCtub")){j=f.fPhi1;q=f.fPhi2-f.fPhi1}var r=Math.max(4,Math.round(q/a.GEO.GradPerSegm));var s=r*(((c[0]<=0)||(c[1]<=0))?1:2);if(l){s+=r*(((d[0]<=0)||(d[1]<=0))?1:2)}if(c[0]>0){s+=r*((d[0]>0)?2:1)}if(c[1]>0){s+=r*((d[1]>0)?2:1)}if(q<360){s+=((c[0]>d[0])?2:0)+((c[1]>d[1])?2:0)}if(n<0){return s}var x=j*Math.PI/180,b=q/r*Math.PI/180,i=new Float32Array(r+1),m=new Float32Array(r+1);for(var t=0;t<=r;++t){m[t]=Math.cos(x+t*b);i[t]=Math.sin(x+t*b)}var o=n?new a.GEO.PolygonsCreator:new a.GEO.GeometryCreator(s);var e;if(f._typename=="TGeoCtub"){e=function(B,D,C){var A=(C<0)?f.fNlow:f.fNhigh;return((C<0)?-f.fDz:f.fDz)-(B*A[0]+D*A[1])/A[2]}}for(var g=0;g<2;++g){if((g===1)&&!l){break}var k=(g===0)?c:d,z=g,y=1-g,h=1,v=0;if(k[0]!==k[1]){var u=Math.atan2((k[1]-k[0]),2*f.fDZ);h=Math.cos(u);v=Math.sin(u)}if(g===1){h*=-1;v*=-1}var p=0;if(k[0]<=0){p=2}else{if(k[1]<=0){p=1}}for(var t=0;t0,v=(h!==360);if(i<0){return(f?4:2)*(d+1)*l}if(i>0){var b=(f?4:2)*(d+1)*l/i;if(b>1){d=Math.round(d/Math.sqrt(b));l=Math.round(l/Math.sqrt(b))}}var g=new THREE.Geometry();var s=new THREE.Color();var w=new THREE.TorusGeometry(e,x,d,l,h*Math.PI/180);w.applyMatrix(new THREE.Matrix4().makeRotationZ(r*Math.PI/180));for(var o=0;o0?4:2)*h*(v+(f.fDphi!==360?1:0));if(q<0){return F}if((q>0)&&(F>q)){h=Math.floor(h/Math.sqrt(F/q));v=Math.floor(v/Math.sqrt(F/q));F=(f.fRmin>0?4:2)*h*(v+(f.fDphi!==360?1:0))}var I=new Float32Array(h+1),y=new Float32Array(h+1),G=new Float32Array(v+1),x=new Float32Array(v+1);for(var C=0;C<=h;++C){I[C]=Math.sin(C/h*2*Math.PI);y[C]=Math.cos(C/h*2*Math.PI)}for(var A=0;A<=v;++A){var H=(f.fPhi1+f.fDphi*A/v)/180*Math.PI;G[A]=Math.sin(H);x[A]=Math.cos(H)}var s=q?new a.GEO.PolygonsCreator:new a.GEO.GeometryCreator(F);var e=new THREE.Vector3(),d=new THREE.Vector3(),c=new THREE.Vector3(),b=new THREE.Vector3(),r=new THREE.Vector3(),p=new THREE.Vector3(),o=new THREE.Vector3(),m=new THREE.Vector3(),l=new THREE.Vector3(),j=new THREE.Vector3();for(var g=0;g<2;++g){if((g>0)&&(f.fRmin<=0)){break}var i=(g>0)?f.fRmin:f.fRmax,L=1-g,J=1-L,K=g>0?-1:1;for(var A=0;A0)?0:1,J=1-L,D=(f.fRmin)>0?0:1,E=A>0?1:-1;for(var C=0;C0){q=true}}var M=p*Math.PI/180,h=w/x*Math.PI/180;var n=new Float32Array(x+1),s=new Float32Array(x+1);for(var B=0;B<=x;++B){s[B]=Math.cos(M+B*h);n[B]=Math.sin(M+B*h)}var J=[[],[]],v=null,m=null;var P=x;if(w!==360){v=[];m=[];P+=1}var L,K,I,F,E;for(var l=0;l<2;++l){var u=(l===0)?"fRmax":"fRmin";var t=r.vertices.length;for(var O=0;O0)&&(O0)&&((l===0)||q)){for(var B=0;B=k.fRmax[O]){continue}var D=J[1][O],H=J[0][O];for(var B=0;B0;--O){if(k.fZ[O]===k.fZ[O-1]){continue}var G=2*k.fNz-1-O;j.push([G,O-1,O]);j.push([G,G+1,O-1])}}else{j=THREE.ShapeUtils.triangulateShape(v,[])}for(var z=0;z0){y=true}}if(x<0){return(y?4:2)*L*(t.fNz-1)}var j=(w===360)?null:[];for(var r=0;r<2;++r){var h=(r===0)?"fRmax":"fRmin";for(var e=0;e0)&&(e0)&&((r===0)||y)){o[e*2+r]=1;O++}if(j!==null){if(r===0){j.push(new THREE.Vector2(f,C))}else{if(f0;--e){if(t.fZ[e]===t.fZ[e-1]){continue}var E=2*t.fNz-1-e;K.push([E,e-1,e]);K.push([E,E+1,e-1])}}else{console.log("trinagulate "+t.fName);K=THREE.ShapeUtils.triangulateShape(j,[]);console.log("trinagulate done "+K.length)}v+=K.length*2}var i=M*Math.PI/180,d=w/L*Math.PI/180;var l=new Float32Array(L+1),g=new Float32Array(L+1);for(var z=0;z<=L;++z){g[z]=Math.cos(i+z*d);l[z]=Math.sin(i+z*d)}var u=x?new a.GEO.PolygonsCreator:new a.GEO.GeometryCreator(v);for(var r=0;r<2;++r){var h=(r===0)?"fRmax":"fRmin",B=t.fZ[0],p=t[h][0],J=1-r,I=r;for(var e=0;e0){G*=-1;F*=-1}for(var z=0;z0)}for(var z=0;z0){for(var h=0;h0){var d=2*(s+1)*(o+1)/m;if(d>1){s=Math.round(s/Math.sqrt(d));o=Math.round(o/Math.sqrt(d))}}var f=new Float32Array(s),l=new Float32Array(s);for(var v=0;v=0){if(e.fB>w){w=e.fB}}else{if(e.fB0){for(var v=0;v0){var c=2*t*(n+1)/l;if(c>1){t=Math.max(5,Math.floor(t/Math.sqrt(c)));n=Math.max(5,Math.floor(n/Math.sqrt(c)))}}var z=-d.fDZ,B=d.fDZ,s=d.fRlo,u=d.fRhi;if(d.fA>=0){if(d.fB>z){z=d.fB}}else{if(d.fB0)?-1:1;var r=0;if(v===0){r=1}else{if(h===0){r=2}}for(var x=0;x0){var c=((d.fRmin<=0)?2:4)*(p+1)*(o+2)/m;if(c>1){p=Math.round(p/Math.sqrt(c));o=Math.round(o/Math.sqrt(c))}}var f=new Float32Array(p),k=new Float32Array(p);for(var s=0;s0){for(var s=0;s0)?4:2);if(f<0){return q}if((f>0)&&(f>q)){m=Math.max(4,Math.floor(m/Math.sqrt(q/f)));k=Math.max(4,Math.floor(k/Math.sqrt(q/f)));q=m*(k+1)*((b.fRmin>0)?4:2)}var d=new Float32Array(m+1),e=new Float32Array(m+1);for(var r=0;r<=m;++r){e[r]=Math.cos(r/m*2*Math.PI);d[r]=Math.sin(r/m*2*Math.PI)}var h=f?new a.GEO.PolygonsCreator:new a.GEO.GeometryCreator(q);for(var c=0;c<2;++c){if((c>0)&&(b.fRmin<=0)){break}var p=(c>0)?b.fRmin:b.fRmax,s=(c>0)?b.fTinsq:b.fToutsq,v=1-c,u=1-v;for(var t=0;t0)?Math.sqrt(b.fRmin*b.fRmin+b.fTinsq*g*g):0,l=(b.fRmin>0)?0:1,v=1-t,u=1-v;for(var r=0;r=0){b=f.stack.split("\n")[1]}else{b=" at: "+b}}a.GEO.warn(d._typename+" err: "+f.message+b)}return c<0?0:null};a.GEO.CreateProjectionMatrix=function(c){var b=new THREE.Matrix4();c.updateMatrixWorld();c.matrixWorldInverse.getInverse(c.matrixWorld);b.multiplyMatrices(c.projectionMatrix,c.matrixWorldInverse);return b};a.GEO.CreateFrustum=function(c){if(!c){return null}if(c instanceof THREE.PerspectiveCamera){c=a.GEO.CreateProjectionMatrix(c)}var b=new THREE.Frustum();b.setFromMatrix(c);b.corners=new Float32Array([1,1,1,1,1,-1,1,-1,1,1,-1,-1,-1,1,1,-1,1,-1,-1,-1,1,-1,-1,-1,0,0,0]);b.test=new THREE.Vector3(0,0,0);b.CheckShape=function(g,f){var j=this.test,d=this.corners.length,e=this.corners,h;for(h=0;h5};return b};a.GEO.VisibleByCamera=function(g,e,d){var h=new THREE.Frustum();var b=new THREE.Matrix4();g.updateMatrixWorld();g.matrixWorldInverse.getInverse(g.matrixWorld);b.multiplyMatrices(g.projectionMatrix,g.matrixWorldInverse);h.setFromMatrix(b);var c=[new THREE.Vector3(d.fDX/2,d.fDY/2,d.fDZ/2),new THREE.Vector3(d.fDX/2,d.fDY/2,-d.fDZ/2),new THREE.Vector3(d.fDX/2,-d.fDY/2,d.fDZ/2),new THREE.Vector3(d.fDX/2,-d.fDY/2,-d.fDZ/2),new THREE.Vector3(-d.fDX/2,d.fDY/2,d.fDZ/2),new THREE.Vector3(-d.fDX/2,d.fDY/2,-d.fDZ/2),new THREE.Vector3(-d.fDX/2,-d.fDY/2,d.fDZ/2),new THREE.Vector3(-d.fDX/2,-d.fDY/2,-d.fDZ/2)];for(var f=0;f1){return}this.nodes=[];var p=[];for(var c=0;c0)?b.matrices[b.last-1]:new THREE.Matrix4();if(h.matrix){b.matrices[b.last]=b.mpool[b.last].fromArray(e.elements);b.matrices[b.last].multiply(b.mpool[b.last+1].fromArray(h.matrix))}else{b.matrices[b.last]=e}}if(h.vis&&(j>=0)){if(!b.func||b.func(h)){f++}}b.counter++;if((h.depth!==undefined)&&(j>h.depth)){j=h.depth}if(b.last>b.stack.length-2){throw"stack capacity is not enough "+b.stack.length}if(h.chlds&&(h.numvischld>0)){var d=b.counter,g=0;b.last++;for(var c=0;c0){e.name+="/"}e.name+=e.obj.fName}}if(d&&e.node.matrix){e.matrix.multiply(new THREE.Matrix4().fromArray(e.node.matrix))}}}return e};a.GEO.ClonedNodes.prototype.FindStackByName=function(j){if(!this.origin){return null}var h=j.split("/");var f=0,i=[];for(var c=0;c0)?j[h-1]:0;if(h>0){d=this.nodes[d.chlds[e]]}var g=undefined;if(m.children){for(var f=0;fh){var e=h*(i?0.8:1);var c=this.GetVolumeBoundary(k.viscnt,e,e/100);l=c.min;b=c.max;if(i){k.domatrix=true;k.frustum=i;k.totalcam=0;k.func=function(m){if(m.vol<=l){if(this.frustum.CheckShape(this.getmatrix(),m)){this.viscnt[m.id]++;this.totalcam+=m.nfaces}}return true};for(var d=0;dh*0.2){j=this.GetVolumeBoundary(k.viscnt,h*0.2,h*0.2/100).min}else{j=0}f=b/((j>0)?(j>0):l)}}k.items=[];k.func=function(m){if(m.vol>l){this.items.push(this.CopyStack())}else{if((j>=0)&&(m.vol>j)){if(this.frustum.CheckShape(this.getmatrix(),m)){this.items.push(this.CopyStack(f))}}}return true};this.ScanVisible(k);return{lst:k.items,complete:l===0}};a.GEO.ClonedNodes.prototype.MergeVisibles=function(f,e){var c=0,b=[];for(var d=0;(dg.shape.factor)){g.shape.factor=g.factor}}c.sort(function(j,i){return i.vol*i.factor-j.vol*j.factor});for(var h=0;h=f){h.done=true}else{if((e>0.01*g.length)&&(i!==undefined)){var b=new Date().getTime();if(b-c>i){return h}}}}h.done=true;return h};return a})); \ No newline at end of file diff --git a/visualisations/JsRoot460/scripts/JSRootGeoPainter.js b/visualisations/JsRoot460/scripts/JSRootGeoPainter.js new file mode 100644 index 0000000..100889f --- /dev/null +++ b/visualisations/JsRoot460/scripts/JSRootGeoPainter.js @@ -0,0 +1,2400 @@ +/** JavaScript ROOT 3D geometry painter + * @file JSRootGeoPainter.js */ + +(function( factory ) { + if ( typeof define === "function" && define.amd ) { + // AMD. Register as an anonymous module. + define( [ 'd3', 'JSRootPainter', 'JSRoot3DPainter', 'JSRootGeoBase' ], factory ); + } else { + + if (typeof JSROOT == 'undefined') + throw new Error('JSROOT is not defined', 'JSRootGeoPainter.js'); + + if (typeof JSROOT.Painter != 'object') + throw new Error('JSROOT.Painter is not defined', 'JSRootGeoPainter.js'); + + if (typeof d3 == 'undefined') + throw new Error('d3 is not defined', 'JSRootGeoPainter.js'); + + if (typeof THREE == 'undefined') + throw new Error('THREE is not defined', 'JSRootGeoPainter.js'); + + factory( d3, JSROOT); + } +} (function( d3, JSROOT ) { + + + if ( typeof define === "function" && define.amd ) + JSROOT.loadScript('$$$style/JSRootGeoPainter.css'); + + if (typeof JSROOT.GEO !== 'object') + console.error('JSROOT.GEO namespace is not defined') + + /** + * @class JSROOT.TGeoPainter Holder of different functions and classes for drawing geometries + */ + + // ======= Geometry painter================================================ + + + JSROOT.TGeoPainter = function( obj ) { + if (obj && (obj._typename.indexOf('TGeoVolume') === 0)) + obj = { _typename:"TGeoNode", fVolume: obj, fName: obj.fName, _geoh: obj._geoh }; + + JSROOT.TObjectPainter.call(this, obj); + + this.no_default_title = true; // do not set title to main DIV + + this.Cleanup(true); + } + + JSROOT.TGeoPainter.prototype = Object.create( JSROOT.TObjectPainter.prototype ); + + JSROOT.TGeoPainter.prototype.CreateToolbar = function(args) { + if (this._toolbar) return; + var painter = this; + var buttonList = [{ + name: 'toImage', + title: 'Save as PNG', + icon: JSROOT.ToolbarIcons.camera, + click: function() { + var dataUrl = painter._renderer.domElement.toDataURL("image/png"); + dataUrl.replace("image/png", "image/octet-stream"); + var link = document.createElement('a'); + if (typeof link.download === 'string') { + document.body.appendChild(link); //Firefox requires the link to be in the body + link.download = "geometry.png"; + link.href = dataUrl; + link.click(); + document.body.removeChild(link); //remove the link when done + } + } + }]; + + if (JSROOT.hpainter && JSROOT.hpainter.nobrowser) + buttonList.push({ + name: 'browser', + title: 'Show hierarchy browser', + icon: JSROOT.ToolbarIcons.arrow_right, + click: function() { + if (JSROOT.hpainter) + JSROOT.hpainter.ToggleFloatBrowser(); + } + }); + + if (JSROOT.gStyle.ContextMenu) + buttonList.push({ + name: 'menu', + title: 'Show context menu', + icon: JSROOT.ToolbarIcons.question, + click: function() { + + var evnt = d3.event; + + d3.event.preventDefault(); + d3.event.stopPropagation(); + + JSROOT.Painter.createMenu(function(menu) { + menu.painter = painter; // set as this in callbacks + painter.FillContextMenu(menu); + menu.show(evnt); + }); + } + }); + + this._toolbar = new JSROOT.Toolbar( this.select_main(), [buttonList] ); + } + + + JSROOT.TGeoPainter.prototype.ModifyVisisbility = function(name, sign) { + var node = this.GetObject(); + + var kind = JSROOT.GEO.NodeKind(node); + var prop = JSROOT.GEO.getNodeProperties(kind, node); + + if (name == "") + return JSROOT.GEO.SetBit(prop.volume, JSROOT.GEO.BITS.kVisThis, (sign === "+")); + + var regexp; + + if (name.indexOf("*") < 0) + regexp = new RegExp(name); + else + regexp = new RegExp("^" + name.split("*").join(".*") + "$"); + + if (prop.chlds!==null) + for (var n=0;n=0) && (pm 0) + for (var n=0;n 0) ? ('/' + names[n]) : ""); + + if (JSROOT.hpainter) { + // show browser if it not visible + if (JSROOT.hpainter.nobrowser && force) + JSROOT.hpainter.ToggleFloatBrowser(true); + + JSROOT.hpainter.actiavte(names, force); + + // if highlight in the browser disabled, suppress in few seconds + if (!this.options.update_browser) + setTimeout(function() { JSROOT.hpainter.actiavte([]); }, 2000); + } + } + + JSROOT.TGeoPainter.prototype.TestMatrixes = function() { + // method can be used to check matrix calculations with current three.js model + + var painter = this, errcnt = 0, totalcnt = 0, totalmax = 0; + + var arg = { + domatrix: true, + func: function(node) { + + var m2 = this.getmatrix(); + + var entry = this.CopyStack(); + + var mesh = painter._clones.CreateObject3D(entry.stack, painter._toplevel, 'mesh'); + + if (!mesh) return true; + + totalcnt++; + + var m1 = mesh.matrixWorld, flip, origm2; + + if (m1.equals(m2)) return true + if ((m1.determinant()>0) && (m2.determinant()<-0.9)) { + flip = THREE.Vector3(1,1,-1); + origm2 = m2; + m2 = m2.clone().scale(flip); + if (m1.equals(m2)) return true; + } + + var max = 0; + for (var k=0;k<16;++k) + max = Math.max(max, Math.abs(m1.elements[k] - m2.elements[k])); + + totalmax = Math.max(max, totalmax); + + if (max < 1e-4) return true; + + console.log(painter._clones.ResolveStack(entry.stack).name, 'maxdiff', max, 'determ', m1.determinant(), m2.determinant()); + + errcnt++; + + return false; + } + }; + + + tm1 = new Date().getTime(); + + var cnt = this._clones.ScanVisible(arg); + + tm2 = new Date().getTime(); + + console.log('Compare matrixes total',totalcnt,'errors',errcnt, 'takes', tm2-tm1, 'maxdiff', totalmax); + } + + + JSROOT.TGeoPainter.prototype.FillContextMenu = function(menu) { + menu.add("header: Draw options"); + + menu.addchk(this.options.update_browser, "Browser update", function() { + this.options.update_browser = !this.options.update_browser; + if (!this.options.update_browser) this.ActiavteInBrowser([]); + }); + menu.addchk(this.options.show_controls, "Show Controls", function() { + this.options.show_controls = !this.options.show_controls; + this.showControlOptions(this.options.show_controls); + }); + menu.addchk(this.TestAxisVisibility, "Show axes", function() { + this.toggleAxisDraw(); + }); + menu.addchk(this.options.wireframe, "Wire frame", function() { + this.options.wireframe = !this.options.wireframe; + this.changeWireFrame(this._scene, this.options.wireframe); + }); + menu.addchk(this.options.highlight, "Highlight volumes", function() { + this.options.highlight = !this.options.highlight; + }); + menu.addchk(this.options.wireframe, "Reset camera position", function() { + this.focusCamera(); + this.Render3D(); + }); + menu.addchk(this._controls.autoRotate, "Autorotate", function() { + this._controls.autoRotate = !this._controls.autoRotate; + this.autorotate(2.5); + }); + menu.addchk(this.options.select_in_view, "Select in view", function() { + this.options.select_in_view = !this.options.select_in_view; + if (this.options.select_in_view) this.startDrawGeometry(); + }); + } + + JSROOT.TGeoPainter.prototype.showControlOptions = function(on) { + + if (this._datgui) { + if (on) return; + + this._datgui.destroy(); + delete this._datgui; + return; + } + if (!on) return; + + var painter = this; + + this._datgui = new dat.GUI({ width: Math.min(650, painter._renderer.domElement.width / 2) }); + + // Clipping Options + + var bound = new THREE.Box3().setFromObject(this._toplevel); + bound.expandByVector(bound.size().multiplyScalar(0.01)); + + var clipFolder = this._datgui.addFolder('Clipping'); + + var toggleX = clipFolder.add(this, 'enableX').name('Enable X').listen(); + toggleX.onChange( function (value) { + painter.enableX = value; + painter._enableSSAO = value ? false : painter._enableSSAO; + painter.updateClipping(); + }); + + if (this.clipX === 0) + this.clipX = (bound.min.x+bound.max.x)/2; + var xclip = clipFolder.add(this, 'clipX', bound.min.x, bound.max.x).name('X Position'); + + xclip.onChange( function (value) { + painter.clipX = value; + if (painter.enableX) painter.updateClipping(); + }); + + var toggleY = clipFolder.add(this, 'enableY').name('Enable Y').listen(); + toggleY.onChange( function (value) { + painter.enableY = value; + painter._enableSSAO = value ? false : painter._enableSSAO; + painter.updateClipping(); + }); + + if (this.clipY === 0) + this.clipY = (bound.min.y + bound.max.y)/2; + var yclip = clipFolder.add(this, 'clipY', bound.min.y, bound.max.y).name('Y Position'); + + yclip.onChange( function (value) { + painter.clipY = value; + if (painter.enableY) painter.updateClipping(); + }); + + var toggleZ = clipFolder.add(this, 'enableZ').name('Enable Z').listen(); + toggleZ.onChange( function (value) { + painter.enableZ = value; + painter._enableSSAO = value ? false : painter._enableSSAO; + painter.updateClipping(); + }); + + if (this.clipZ === 0) + this.clipZ = (bound.min.z + bound.max.z) / 2; + var zclip = clipFolder.add(this, 'clipZ', bound.min.z, bound.max.z).name('Z Position'); + + zclip.onChange( function (value) { + painter.clipZ = value; + if (painter.enableZ) painter.updateClipping(); + }); + + // Appearance Options + + var appearance = this._datgui.addFolder('Appearance'); + + if (this._webgl) { + appearance.add(this, '_enableSSAO').name('Smooth Lighting (SSAO)').onChange( function (value) { + painter._renderer.antialias = !painter._renderer.antialias; + painter.enableX = value ? false : painter.enableX; + painter.enableY = value ? false : painter.enableY; + painter.enableZ = value ? false : painter.enableZ; + painter.updateClipping(); + }).listen(); + } + + appearance.add(this.options, 'highlight').name('Highlight Selection').onChange( function (value) { + if (value === false) { + if (painter._selected.mesh !== null) { + painter._selected.mesh.material.color = painter._selected.originalColor; + painter.Render3D(0); + painter._selected.mesh = null; + } + } + }); + + appearance.add(this, 'globalTransparency', 0.0, 1.0).listen().onChange( function (value) { + painter._toplevel.traverse( function (node) { + if (node instanceof THREE.Mesh) { + if (node.material.alwaysTransparent !== undefined) { + if (!node.material.alwaysTransparent) { + node.material.transparent = value !== 1.0; + } + node.material.opacity = Math.min(value * value, node.material.inherentOpacity); + } + + } + }); + painter.Render3D(0); + }); + + appearance.add(this.options, 'wireframe').name('Wireframe').onChange( function (value) { + painter.changeWireFrame(painter._scene, painter.options.wireframe); + }); + + appearance.add(this, 'focusCamera').name('Reset camera position'); + + // Advanced Options + + if (this._webgl) { + var advanced = this._datgui.addFolder('Advanced'); + + advanced.add( this._advceOptions, 'aoClamp', 0.0, 1.0).listen().onChange( function (value) { + painter._ssaoPass.uniforms[ 'aoClamp' ].value = value; + painter._enableSSAO = true; + painter.Render3D(0); + }); + + advanced.add( this._advceOptions, 'lumInfluence', 0.0, 1.0).listen().onChange( function (value) { + painter._ssaoPass.uniforms[ 'lumInfluence' ].value = value; + painter._enableSSAO = true; + painter.Render3D(0); + }); + + advanced.add( this._advceOptions, 'clipIntersection').listen().onChange( function (value) { + painter._renderer.clipIntersection = value; + painter.Render3D(0); + }); + + advanced.add(this._advceOptions, 'depthTest').onChange( function (value) { + painter._toplevel.traverse( function (node) { + if (node instanceof THREE.Mesh) { + node.material.depthTest = value; + } + }); + painter.Render3D(0); + }).listen(); + + advanced.add(this, 'resetAdvanced').name('Reset'); + } + } + + + JSROOT.TGeoPainter.prototype.OrbitContext = function(evnt, intersects) { + + var painter = this; + + JSROOT.Painter.createMenu(function(menu) { + menu.painter = painter; // set as this in callbacks + + if (!intersects || (intersects.length==0)) { + painter.FillContextMenu(menu); + } else { + var many = (intersects.length > 1); + + if (many) menu.add("header: Nodes"); + + for (var n=0;n 0) hdr = name; else + if (painter.GetItemName()) hdr = painter.GetItemName(); + + menu.add((many ? "sub:" : "header:") + hdr, name, function(arg) { this.ActiavteInBrowser([arg], true); }); + + menu.add("Browse", name, function(arg) { this.ActiavteInBrowser([arg], true); }); + + var wireframe = painter.accessObjectWireFrame(obj); + + if (wireframe!==undefined) + menu.addchk(wireframe, "Wireframe", n, function(indx) { + var m = intersects[indx].object.material; + m.wireframe = !m.wireframe; + this.Render3D(); + }); + + if (n>0) + menu.add("Manifest", n, function(indx) { + + if (this._last_manifest) + this._last_manifest.wireframe = !this._last_manifest.wireframe; + + if (this._last_hidden) + this._last_hidden.forEach(function(obj) { obj.visible = true; }); + + this._last_hidden = []; + + for (var i=0;i=0;--n) { + + var unique = intersects[n].object.stack !== undefined; + + for (var k=0;(k this._clipPlanes[0].constant ) { + clipped = true; + } + if (this.enableY && this._clipPlanes[1].normal.dot(point) > this._clipPlanes[1].constant ) { + clipped = true; + } + if (this.enableZ && this._clipPlanes[2].normal.dot(point) > this._clipPlanes[2].constant ) { + clipped = true; + } + + if (clipped) + clippedIntersects.push(intersects[i]); + } + + intersects = clippedIntersects; + } + + return intersects; + } + + JSROOT.TGeoPainter.prototype.testCameraPositionChange = function() { + // function analyzes camera position and start redraw of geometry if + // objects in view may be changed + + if (!this.options.select_in_view || this._draw_all_nodes) return; + + + var matrix = JSROOT.GEO.CreateProjectionMatrix(this._camera); + + var frustum = JSROOT.GEO.CreateFrustum(matrix); + + // check if overall bounding box seen + if (!frustum.CheckBox(new THREE.Box3().setFromObject(this._toplevel))) + this.startDrawGeometry(); + } + + JSROOT.TGeoPainter.prototype.addOrbitControls = function() { + + if (this._controls) return; + + this.select_main().property('flex_block_drag', true); + + var painter = this; + + this._controls = JSROOT.Painter.CreateOrbitControl(this, this._camera, this._scene, this._renderer, this._lookat); + + this._controls.ContextMenu = this.OrbitContext.bind(this); + + this._controls.ProcessMouseMove = function(intersects) { + + var tooltip = null; + + if (painter.options.highlight) { + + if (painter._selected.mesh !== null) { + painter._selected.mesh.material.color = painter._selected.originalColor; + } + + if (intersects.length > 0) { + painter._selected.mesh = intersects[0].object; + painter._selected.originalColor = painter._selected.mesh.material.color; + painter._selected.mesh.material.color = new THREE.Color( 0xffaa33 ); + painter.Render3D(0); + + if (intersects[0].object.stack) + tooltip = painter._clones.ResolveStack(intersects[0].object.stack).name; + } + } + + if (intersects.length === 0 && painter._selected.mesh !== null) { + painter._selected.mesh.material.color = painter._selected.originalColor; + painter.Render3D(0); + painter._selected.mesh = null; + } + + var names = []; + + if (painter.options.update_browser) { + if (painter.options.highlight) { + if (tooltip !== null) names.push(tooltip); + } else { + for (var n=0;n0) { + if (!this._worker) { this.startWorker(); return 1; } + if (!this._worker_ready) return 1; + } + + // first copy visibility flags and check how many unique visible nodes exists + var numvis = this._clones.MarkVisisble(), + matrix = null, frustum = null; + + if (this.options.select_in_view && !this._first_drawing) { + // extract camera projection matrix for selection + + matrix = JSROOT.GEO.CreateProjectionMatrix(this._camera); + + frustum = JSROOT.GEO.CreateFrustum(matrix); + + // check if overall bounding box seen + if (frustum.CheckBox(new THREE.Box3().setFromObject(this._toplevel))) { + matrix = null; // not use camera for the moment + frustum = null; + } + } + + this._current_face_limit = this.options.maxlimit; + if (matrix) this._current_face_limit*=1.25; + + // here we decide if we need worker for the drawings + // main reason - too large geometry and large time to scan all camera positions + var need_worker = (numvis > 10000) || (matrix && (this._clones.ScanVisible() > 1e5)); + // need_worker = false; + + if (need_worker && !this._worker && (this.options.use_worker >= 0)) + this.startWorker(); // we starting worker, but it may not be ready so fast + + if (!need_worker || !this._worker_ready) { + //var tm1 = new Date().getTime(); + var res = this._clones.CollectVisibles(this._current_face_limit, frustum); + this._new_draw_nodes = res.lst; + this._draw_all_nodes = res.complete; + //var tm2 = new Date().getTime(); + //console.log('Collect visibles', this._new_draw_nodes.length, 'takes', tm2-tm1); + this.drawing_stage = 3; + return true; + } + + var job = { + collect: this._current_face_limit, // indicator for the command + visible: this._clones.GetVisibleFlags(), + matrix: matrix ? matrix.elements : null + }; + + this.submitToWorker(job); + + this.drawing_stage = 2; + + this.drawing_log = "Worker select visibles"; + + return 2; // we now waiting for the worker reply + } + + if (this.drawing_stage == 2) { + // do nothing, we are waiting for worker reply + + this.drawing_log = "Worker select visibles"; + + return 2; + } + + if (this.drawing_stage == 3) { + // here we merge new and old list of nodes for drawing, + // normally operation is fast and can be implemented with one call + + this.drawing_log = "Analyse visibles"; + + if (this._draw_nodes) { + var del = this._clones.MergeVisibles(this._new_draw_nodes, this._draw_nodes); + // remove should be fast, do it here + for (var n=0;n 0) + this.drawing_log = "Delete " + del.length + " nodes"; + } + + this._draw_nodes = this._new_draw_nodes; + delete this._new_draw_nodes; + this.drawing_stage = 4; + return true; + } + + if (this.drawing_stage === 4) { + + this.drawing_log = "Collect shapes"; + + // collect shapes + var shapes = this._clones.CollectShapes(this._draw_nodes); + + // merge old and new list with produced shapes + this._build_shapes = this._clones.MergeShapesLists(this._build_shapes, shapes); + + this.drawing_stage = 5; + return true; + } + + + if (this.drawing_stage === 5) { + // this is building of geometries, + // one can ask worker to build them or do it ourself + + if (this.canSubmitToWorker()) { + var job = { limit: this._current_face_limit, shapes: [] }, cnt = 0; + for (var n=0;n 0) { + /// only if some geom missing, submit job to the worker + this.submitToWorker(job); + this.drawing_log = "Worker build shapes"; + this.drawing_stage = 6; + return 2; + } + } + + this.drawing_stage = 7; + } + + if (this.drawing_stage === 6) { + // waiting shapes from the worker, worker should activate our code + return 2; + } + + if ((this.drawing_stage === 7) || (this.drawing_stage === 8)) { + + if (this.drawing_stage === 7) { + // building shapes + var res = this._clones.BuildShapes(this._build_shapes, this._current_face_limit, 500); + if (res.done) { + this.drawing_stage = 8; + } else { + this.drawing_log = "Creating: " + res.shapes + " / " + this._build_shapes.length + " shapes, " + res.faces + " faces"; + if (res.notusedshapes < 30) return true; + } + } + + // final stage, create all meshes + + var tm0 = new Date().getTime(), ready = true; + + for (var n=0; n 1e-5) && (Math.abs(v2-v1)/mean > 1e-6)) ndiff++; + } + if (ndiff>0) console.log('Mismatch for ' + info.name, info.matrix.elements, obj3d.matrixWorld.elements); +*/ + + var nodeobj = this._clones.origin[entry.nodeid]; + var clone = this._clones.nodes[entry.nodeid]; + var prop = JSROOT.GEO.getNodeProperties(clone.kind, nodeobj, true); + + this._num_meshes++; + this._num_faces += shape.nfaces; + + prop.material.wireframe = this.options.wireframe; + + prop.material.side = this.bothSides ? THREE.DoubleSide : THREE.FrontSide; + + var mesh; + + if (obj3d.matrixWorld.determinant() > -0.9) { + mesh = new THREE.Mesh( shape.geom, prop.material ); + } else { + mesh = this.createFlippedMesh(obj3d, shape, prop.material); + } + + // keep full stack of nodes + mesh.stack = entry.stack; + + obj3d.add(mesh); + + if (this.options._debug || this.options._full) { + var helper = new THREE.WireframeHelper(mesh); + helper.material.color.set(prop.fillcolor); + helper.material.linewidth = ('fVolume' in nodeobj) ? nodeobj.fVolume.fLineWidth : 1; + obj3d.add(helper); + } + + if (this.options._bound || this.options._full) { + var boxHelper = new THREE.BoxHelper( mesh ); + obj3d.add( boxHelper ); + } + + var tm1 = new Date().getTime(); + if (tm1 - tm0 > 500) { ready = false; break; } + } + + if (ready) { + this.drawing_log = "Building done"; + this.drawing_stage = 0; + return false; + } + + if (this.drawing_stage > 7) + this.drawing_log = "Building meshes " + this._num_meshes + " / " + this._num_faces; + return true; + } + + console.log('never come here'); + + return false; + + + } + + JSROOT.TGeoPainter.prototype.SameMaterial = function(node1, node2) { + + if ((node1===null) || (node2===null)) return node1 === node2; + + if (node1.fVolume.fLineColor >= 0) + return (node1.fVolume.fLineColor === node2.fVolume.fLineColor); + + var m1 = (node1.fVolume.fMedium !== null) ? node1.fVolume.fMedium.fMaterial : null; + var m2 = (node2.fVolume.fMedium !== null) ? node2.fVolume.fMedium.fMaterial : null; + + if (m1 === m2) return true; + + if ((m1 === null) || (m2 === null)) return false; + + return (m1.fFillStyle === m2.fFillStyle) && (m1.fFillColor === m2.fFillColor); + } + + JSROOT.TGeoPainter.prototype.createScene = function(webgl, w, h, pixel_ratio) { + // three.js 3D drawing + this._scene = new THREE.Scene(); + this._scene.fog = new THREE.Fog(0xffffff, 1, 10000); + this._scene.overrideMaterial = new THREE.MeshLambertMaterial( { color: 0x7000ff, transparent: true, opacity: 0.2, depthTest: false } ); + + this._scene_width = w; + this._scene_height = h; + + this._camera = new THREE.PerspectiveCamera(25, w / h, 1, 10000); + + this._camera.up = this.options._yup ? new THREE.Vector3(0,1,0) : new THREE.Vector3(0,0,1); + this._scene.add( this._camera ); + + this._selected = {mesh:null, originalColor:null}; + + this._overall_size = 10; + + this._toplevel = new THREE.Object3D(); + + this._scene.add(this._toplevel); + + this._renderer = webgl ? + new THREE.WebGLRenderer({ antialias : true, logarithmicDepthBuffer: false, + preserveDrawingBuffer: true }) : + new THREE.CanvasRenderer({antialias : true }); + this._renderer.setPixelRatio(pixel_ratio); + this._renderer.setClearColor(0xffffff, 1); + this._renderer.setSize(w, h); + this._renderer.clipIntersection = true; + + this._animating = false; + + // Clipping Planes + + this.bothSides = false; // which material kind should be used + this.enableX = this.enableY = this.enableZ = false; + this.clipX = this.clipY = this.clipZ = 0.0; + + this._clipPlanes = [ new THREE.Plane(new THREE.Vector3( 1, 0, 0), this.clipX), + new THREE.Plane(new THREE.Vector3( 0, this.options._yup ? -1 : 1, 0), this.clipY), + new THREE.Plane(new THREE.Vector3( 0, 0, this.options._yup ? 1 : -1), this.clipZ) ]; + + // Lights + + //var light = new THREE.HemisphereLight( 0xffffff, 0x999999, 0.5 ); + //this._scene.add(light); + + /* + var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.2 ); + directionalLight.position.set( 0, 1, 0 ); + this._scene.add( directionalLight ); + + this._lights = new THREE.Object3D(); + var a = new THREE.PointLight(0xefefef, 0.2); + var b = new THREE.PointLight(0xefefef, 0.2); + var c = new THREE.PointLight(0xefefef, 0.2); + var d = new THREE.PointLight(0xefefef, 0.2); + this._lights.add(a); + this._lights.add(b); + this._lights.add(c); + this._lights.add(d); + this._camera.add( this._lights ); + a.position.set( 20000, 20000, 20000 ); + b.position.set( -20000, 20000, 20000 ); + c.position.set( 20000, -20000, 20000 ); + d.position.set( -20000, -20000, 20000 ); + */ + this._pointLight = new THREE.PointLight(0xefefef, 1); + this._camera.add( this._pointLight ); + this._pointLight.position.set(10, 10, 10); + //*/ + + // Default Settings + + this.globalTransparency = 1.0; + + this._defaultAdvanced = { aoClamp: 0.70, + lumInfluence: 0.4, + // shininess: 100, + clipIntersection: true, + depthTest: true + }; + + // Smooth Lighting Shader (Screen Space Ambient Occulsion) + // http://threejs.org/examples/webgl_postprocessing_ssao.html + + this._enableSSAO = false; + + if (webgl) { + var renderPass = new THREE.RenderPass( this._scene, this._camera ); + // Setup depth pass + this._depthMaterial = new THREE.MeshDepthMaterial( { side: THREE.DoubleSide }); + this._depthMaterial.depthPacking = THREE.RGBADepthPacking; + this._depthMaterial.blending = THREE.NoBlending; + var pars = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter }; + this._depthRenderTarget = new THREE.WebGLRenderTarget( w, h, pars ); + // Setup SSAO pass + this._ssaoPass = new THREE.ShaderPass( THREE.SSAOShader ); + this._ssaoPass.renderToScreen = true; + this._ssaoPass.uniforms[ "tDepth" ].value = this._depthRenderTarget.texture; + this._ssaoPass.uniforms[ 'size' ].value.set( w, h ); + this._ssaoPass.uniforms[ 'cameraNear' ].value = this._camera.near; + this._ssaoPass.uniforms[ 'cameraFar' ].value = this._camera.far; + this._ssaoPass.uniforms[ 'onlyAO' ].value = false;//( postprocessing.renderMode == 1 ); + this._ssaoPass.uniforms[ 'aoClamp' ].value = this._defaultAdvanced.aoClamp; + this._ssaoPass.uniforms[ 'lumInfluence' ].value = this._defaultAdvanced.lumInfluence; + // Add pass to effect composer + this._effectComposer = new THREE.EffectComposer( this._renderer ); + this._effectComposer.addPass( renderPass ); + this._effectComposer.addPass( this._ssaoPass ); + } + + this._advceOptions = {}; + this.resetAdvanced(); + } + + + JSROOT.TGeoPainter.prototype.startDrawGeometry = function(force) { + + if (!force && (this.drawing_stage!==0)) { + this._draw_nodes_again = true; + return; + } + + this._startm = new Date().getTime(); + this._last_render_tm = this._startm; + this._last_render_meshes = 0; + this.drawing_stage = 1; + this.drawing_log = "collect visible"; + this._num_meshes = 0; + this._num_faces = 0; + + delete this._last_manifest; + delete this._last_hidden; // clear list of hidden objects + + delete this._draw_nodes_again; // forget about such flag + + this.continueDraw(); + } + + JSROOT.TGeoPainter.prototype.resetAdvanced = function() { + if (this._webgl) { + this._advceOptions.aoClamp = this._defaultAdvanced.aoClamp; + this._advceOptions.lumInfluence = this._defaultAdvanced.lumInfluence; + + this._ssaoPass.uniforms[ 'aoClamp' ].value = this._defaultAdvanced.aoClamp; + this._ssaoPass.uniforms[ 'lumInfluence' ].value = this._defaultAdvanced.lumInfluence; + } + + this._advceOptions.depthTest = this._defaultAdvanced.depthTest; + this._advceOptions.clipIntersection = this._defaultAdvanced.clipIntersection; + this._renderer.clipIntersection = this._defaultAdvanced.clipIntersection; + + var painter = this; + this._toplevel.traverse( function (node) { + if (node instanceof THREE.Mesh) { + node.material.depthTest = painter._defaultAdvanced.depthTest; + } + }); + + this.Render3D(0); + } + + JSROOT.TGeoPainter.prototype.updateMaterialSide = function(both_sides, force) { + if ((this.bothSides === both_sides) && !force) return; + + this._scene.traverse( function(obj) { + if (obj.hasOwnProperty("material") && ('emissive' in obj.material)) { + obj.material.side = both_sides ? THREE.DoubleSide : THREE.FrontSide; + obj.material.needsUpdate = true; + } + }); + this.bothSides = both_sides; + } + + JSROOT.TGeoPainter.prototype.updateClipping = function(without_render) { + this._clipPlanes[0].constant = this.clipX; + this._clipPlanes[1].constant = -this.clipY; + this._clipPlanes[2].constant = this.options._yup ? -this.clipZ : this.clipZ; + this._renderer.clippingPlanes = []; + if (this.enableX) this._renderer.clippingPlanes.push(this._clipPlanes[0]); + if (this.enableY) this._renderer.clippingPlanes.push(this._clipPlanes[1]); + if (this.enableZ) this._renderer.clippingPlanes.push(this._clipPlanes[2]); + + this.updateMaterialSide(this.enableX || this.enableY || this.enableZ); + + if (!without_render) this.Render3D(0); + } + + JSROOT.TGeoPainter.prototype.adjustCameraPosition = function(first_time) { + + var box = new THREE.Box3().setFromObject(this._toplevel); + + var sizex = box.max.x - box.min.x, + sizey = box.max.y - box.min.y, + sizez = box.max.z - box.min.z, + midx = (box.max.x + box.min.x)/2, + midy = (box.max.y + box.min.y)/2, + midz = (box.max.z + box.min.z)/2; + + this._overall_size = 2 * Math.max( sizex, sizey, sizez); + + this._scene.fog.near = this._overall_size * 2; + this._camera.near = this._overall_size / 350; + this._scene.fog.far = this._overall_size * 12; + this._camera.far = this._overall_size * 12; + + if (this._webgl) { + this._ssaoPass.uniforms[ 'cameraNear' ].value = this._camera.near;//*this._nFactor; + this._ssaoPass.uniforms[ 'cameraFar' ].value = this._camera.far;///this._nFactor; + } + + if (first_time) { + this.clipX = midx; + this.clipY = midy; + this.clipZ = midz; + } + + // this._camera.far = 100000000000; + + this._camera.updateProjectionMatrix(); + + if (this.options._yup) { + this._camera.position.set(midx-2*Math.max(sizex,sizez), midy+2*sizey, midz-2*Math.max(sizex,sizez)); + } else { + this._camera.position.set(midx-2*Math.max(sizex,sizey), midy-2*Math.max(sizex,sizey), midz+2*sizez); + } + + this._lookat = new THREE.Vector3(midx, midy, midz); + this._camera.lookAt(this._lookat); + + this._pointLight.position.set(sizex/5, sizey/5, sizez/5); + + if (this._controls) { + this._controls.target.copy(this._lookat); + this._controls.update(); + } + + // recheck which elements to draw + if (this.options.select_in_view) + this.startDrawGeometry(); + } + + JSROOT.TGeoPainter.prototype.focusOnItem = function(itemname) { + + if (!itemname || (itemname.indexOf('Nodes/')!==0) || !this._clones) return; + + var stack = this._clones.FindStackByName(itemname.substr(6)); + + if (!stack) return; + + var info = this._clones.ResolveStack(stack, true); + + //console.log( info ); + + //console.log('transfrom matrix', info.matrix.elements); + + //console.log('shape dimensions', info.node.fDX, info.node.fDY, info.node.fDZ); + + this.focusCamera( info, false ); + } + + JSROOT.TGeoPainter.prototype.focusCamera = function( focus, clip ) { + + var autoClip = clip === undefined ? false : clip; + + var box = new THREE.Box3(); + if (focus === undefined) { + box.setFromObject(this._toplevel); + } else if (focus instanceof THREE.Mesh) { + box.setFromObject(focus); + } else { + var center = new THREE.Vector3().setFromMatrixPosition(focus.matrix); + var node = focus.node; + var halfDelta = new THREE.Vector3( node.fDX, node.fDY, node.fDZ ).multiplyScalar(0.5); + box.min = center.clone().sub(halfDelta) ; + box.max = center.clone().add(halfDelta) ; + } + + var sizex = box.max.x - box.min.x, + sizey = box.max.y - box.min.y, + sizez = box.max.z - box.min.z, + midx = (box.max.x + box.min.x)/2, + midy = (box.max.y + box.min.y)/2, + midz = (box.max.z + box.min.z)/2; + + var position; + if (this.options._yup) + position = new THREE.Vector3(midx-2*Math.max(sizex,sizez), midy+2*sizey, midz-2*Math.max(sizex,sizez)); + else + position = new THREE.Vector3(midx-2*Math.max(sizex,sizey), midy-2*Math.max(sizex,sizey), midz+2*sizez); + + var target = new THREE.Vector3(midx, midy, midz); + //console.log("Zooming to x: " + target.x + " y: " + target.y + " z: " + target.z ); + + + // Find to points to animate "lookAt" between + var dist = this._camera.position.distanceTo(target); + var oldTarget = this._controls.target; + + var frames = 200; + var step = 0; + // Amount to change camera position at each step + var posIncrement = position.sub(this._camera.position).divideScalar(frames); + // Amount to change "lookAt" so it will end pointed at target + var targetIncrement = target.sub(oldTarget).divideScalar(frames); + console.log( targetIncrement ); + + // Automatic Clipping + + if (autoClip) { + + var topBox = new THREE.Box3().setFromObject(this._toplevel); + + this.clipX = this.enableX ? this.clipX : topBox.min.x; + this.clipY = this.enableY ? this.clipY : topBox.min.y; + this.clipZ = this.enableZ ? this.clipZ : topBox.min.z; + + this.enableX = this.enableY = this.enableZ = true; + + // These should be center of volume, box may not be doing this correctly + var incrementX = ((box.max.x + box.min.x) / 2 - this.clipX) / frames, + incrementY = ((box.max.y + box.min.y) / 2 - this.clipY) / frames, + incrementZ = ((box.max.z + box.min.z) / 2 - this.clipZ) / frames; + + this.updateClipping(); + } + + var painter = this; + this._animating = true; + this._controls.autoRotate = false; + + // Interpolate // + + function animate() { + if (painter._animating) { + requestAnimationFrame( animate ); + } else { + painter.startDrawGeometry(); + } + var smoothFactor = -Math.cos( ( 2.0 * Math.PI * step ) / frames ) + 1.0; + painter._camera.position.add( posIncrement.clone().multiplyScalar( smoothFactor ) ); + oldTarget.add( targetIncrement.clone().multiplyScalar( smoothFactor ) ); + painter._lookat = oldTarget; + painter._camera.lookAt( painter._lookat ); + painter._camera.updateProjectionMatrix(); + if (autoClip) { + painter.clipX += incrementX * smoothFactor; + painter.clipY += incrementY * smoothFactor; + painter.clipZ += incrementZ * smoothFactor; + painter.updateClipping(); + } else { + painter.Render3D(); + } + step++; + painter._animating = step < frames; + } + animate(); + + // this._controls.update(); + + } + + JSROOT.TGeoPainter.prototype.autorotate = function(speed) { + + var rotSpeed = speed === undefined ? 2.0 : speed; + var painter = this; + var last = new Date(); + function animate() { + var current = new Date(); + + if ( painter._controls.autoRotate ) requestAnimationFrame( animate ); + + painter._controls.autoRotateSpeed = rotSpeed * ( current.getTime() - last.getTime() ) / 16.6666; + painter._controls.update(); + last = new Date(); + painter.Render3D(0); + } + animate(); + } + + JSROOT.TGeoPainter.prototype.completeScene = function() { + + if ( this.options._debug || this.options._grid ) { + if ( this.options._full ) { + var boxHelper = new THREE.BoxHelper(this._toplevel); + this._scene.add( boxHelper ); + } + this._scene.add( new THREE.AxisHelper( 2 * this._overall_size ) ); + this._scene.add( new THREE.GridHelper( Math.ceil( this._overall_size), Math.ceil( this._overall_size ) / 50 ) ); + this.helpText("
Transform Controls
" + + "'T' translate | 'R' rotate | 'S' scale
" + + "'+' increase size | '-' decrease size
" + + "'W' toggle wireframe/solid display
"+ + "keep 'Ctrl' down to snap to grid
"); + } + } + + + JSROOT.TGeoPainter.prototype.drawCount = function(unqievis, clonetm) { + + var res = 'Unique nodes: ' + this._clones.nodes.length + '
' + + 'Unique visible: ' + unqievis + '
' + + 'Time to clone: ' + clonetm + 'ms
'; + + // need to fill cached value line numvischld + this._clones.ScanVisible(); + + var arg = { + cnt: [], + func: function(node) { + if (this.cnt[this.last]===undefined) + this.cnt[this.last] = 1; + else + this.cnt[this.last]++; + return true; + } + }; + + var tm1 = new Date().getTime(); + var numvis = this._clones.ScanVisible(arg); + var tm2 = new Date().getTime(); + + res += 'Total visible nodes: ' + numvis + '
'; + + for (var lvl=0;lvl'); + } + + res += "Time to scan: " + (tm2-tm1) + "ms
"; + + res += "

Check timing for matrix calculations ...
"; + + var elem = this.select_main().style('overflow', 'auto').html(res); + + var painter = this; + + setTimeout(function() { + arg.domatrix = true; + tm1 = new Date().getTime(); + numvis = painter._clones.ScanVisible(arg); + tm2 = new Date().getTime(); + elem.append("p").text("Time to scan with matrix: " + (tm2-tm1) + "ms"); + }, 100); + + return this.DrawingReady(); + } + + + JSROOT.TGeoPainter.prototype.DrawGeometry = function(opt) { + if (typeof opt !== 'string') opt = ""; + + var size = this.size_for_3d(); + + this._webgl = JSROOT.Painter.TestWebGL(); + + this.options = this.decodeOptions(opt); + + if (!('_yup' in this.options)) + this.options._yup = this.svg_canvas().empty(); + + var tm1 = new Date().getTime(); + + this._clones = new JSROOT.GEO.ClonedNodes(this.GetObject()); + var uniquevis = this._clones.MarkVisisble(true); + if (uniquevis <= 0) + uniquevis = this._clones.MarkVisisble(false); + else + uniquevis = this._clones.MarkVisisble(true, true); // copy bits once and use normal visibility bits + + var tm2 = new Date().getTime(); + + console.log('Creating clones', this._clones.nodes.length, 'takes', tm2-tm1, 'uniquevis', uniquevis); + + if (this.options._count) + return this.drawCount(uniquevis, tm2-tm1); + + // this is limit for the visible faces, number of volumes does not matter + this.options.maxlimit = (this._webgl ? 200000 : 100000) * this.options.more; + + this._first_drawing = true; + + // activate worker + if (this.options.use_worker > 0) this.startWorker(); + + this.createScene(this._webgl, size.width, size.height, window.devicePixelRatio); + + this.add_3d_canvas(size, this._renderer.domElement); + + this.CreateToolbar(); + + this.startDrawGeometry(true); + + return this; + } + + JSROOT.TGeoPainter.prototype.continueDraw = function() { + + // nothing to do - exit + if (this.drawing_stage === 0) return; + + var tm0 = new Date().getTime(), + interval = this._first_drawing ? 1000 : 200, + now = tm0; + + while(true) { + + var res = this.nextDrawAction(); + + if (!res) break; + + now = new Date().getTime(); + + // stop creation after 100 sec, render as is + if (now - this._startm > 1e5) { + this.drawing_stage = 0; + break; + } + + // if we are that fast, do next action + if ((res===true) && (now - tm0 < interval)) continue; + + if ((now - tm0 > interval) || (res === 1) || (res === 2)) { + + JSROOT.progress(this.drawing_log); + + if (this._first_drawing && this._webgl && (this._num_meshes - this._last_render_meshes > 100) && (now - this._last_render_tm > 2.5*interval)) { + this.adjustCameraPosition(); + this.Render3D(-1); + this._last_render_tm = new Date().getTime(); + this._last_render_meshes = this._num_meshes; + } + if (res !== 2) setTimeout(this.continueDraw.bind(this), (res === 1) ? 100 : 1); + return; + } + } + + var take_time = now - this._startm; + + if (this._first_drawing) + JSROOT.console('Create tm = ' + take_time + ' meshes ' + this._num_meshes + ' faces ' + this._num_faces); + + if (take_time > 300) { + JSROOT.progress('Rendering geometry'); + return setTimeout(this.completeDraw.bind(this, true), 10); + } + + this.completeDraw(true); + } + + JSROOT.TGeoPainter.prototype.Render3D = function(tmout, measure) { + if (tmout === undefined) tmout = 5; // by default, rendering happens with timeout + + if (tmout <= 0) { + if ('render_tmout' in this) + clearTimeout(this.render_tmout); + + var tm1 = new Date(); + + if (typeof this.TestAxisVisibility === 'function') + this.TestAxisVisibility(this._camera, this._toplevel); + + // do rendering, most consuming time + if (this._webgl && this._enableSSAO) { + this._scene.overrideMaterial = this._depthMaterial; + // this._renderer.logarithmicDepthBuffer = false; + this._renderer.render(this._scene, this._camera, this._depthRenderTarget, true); + this._scene.overrideMaterial = null; + this._effectComposer.render(); + } else { + // this._renderer.logarithmicDepthBuffer = true; + this._renderer.render(this._scene, this._camera); + } + + var tm2 = new Date(); + + this.last_render_tm = tm2.getTime() - tm1.getTime(); + + delete this.render_tmout; + + if ((this.first_render_tm === 0) && measure) { + this.first_render_tm = this.last_render_tm; + JSROOT.console('First render tm = ' + this.first_render_tm); + } + + return; + } + + // do not shoot timeout many times + if (!this.render_tmout) + this.render_tmout = setTimeout(this.Render3D.bind(this,0,measure), tmout); + } + + + JSROOT.TGeoPainter.prototype.startWorker = function() { + + if (this._worker) return; + + this._worker_ready = false; + this._worker_jobs = 0; // counter how many requests send to worker + + var pthis = this; + + this._worker = new Worker(JSROOT.source_dir + "scripts/JSRootGeoWorker.js"); + + this._worker.onmessage = function(e) { + + if (typeof e.data !== 'object') return; + + if ('log' in e.data) + return JSROOT.console('geo: ' + e.data.log); + + if ('progress' in e.data) + return JSROOT.progress(e.data.progress); + + e.data.tm3 = new Date().getTime(); + + if ('init' in e.data) { + pthis._worker_ready = true; + return JSROOT.console('Worker ready: ' + (e.data.tm3 - e.data.tm0)); + } + + pthis.processWorkerReply(e.data); + }; + + // send initialization message with clones + this._worker.postMessage( { init: true, tm0: new Date().getTime(), clones: this._clones.nodes, sortmap: this._clones.sortmap } ); + } + + JSROOT.TGeoPainter.prototype.canSubmitToWorker = function(force) { + if (!this._worker) return false; + + return this._worker_ready && ((this._worker_jobs == 0) || force); + } + + JSROOT.TGeoPainter.prototype.submitToWorker = function(job) { + if (!this._worker) return false; + + this._worker_jobs++; + + job.tm0 = new Date().getTime(); + + this._worker.postMessage(job); + } + + JSROOT.TGeoPainter.prototype.processWorkerReply = function(job) { + this._worker_jobs--; + + if ('collect' in job) { + this._new_draw_nodes = job.new_nodes; + this._draw_all_nodes = job.complete; + this.drawing_stage = 3; + // invoke methods immediately + return this.continueDraw(); + } + + if ('shapes' in job) { + + for (var n=0;n 0) sub._title += " " + obj.fTitle; + volume = obj.fVolume; + } else + if (obj._typename.indexOf("TGeoVolume")===0) { + volume = obj; + } else + if (obj._typename == "TEveGeoShapeExtract") { + shape = obj.fShape; + subnodes = obj.fElements ? obj.fElements.arr : null; + } else + if ((obj.fShapeBits !== undefined) && (obj.fShapeId !== undefined)) { + shape = obj; + } + + if (volume) { + shape = volume.fShape; + subnodes = volume.fNodes ? volume.fNodes.arr : null; + } + + if (volume || shape || subnodes) { + if (volume) sub._volume = volume; + + if (subnodes) { + sub._more = true; + sub._expand = JSROOT.GEO.expandObject; + } else + if (shape && (shape._typename === "TGeoCompositeShape") && shape.fNode) { + sub._more = true; + sub._shape = shape; + sub._expand = function(node, obj) { + JSROOT.GEO.createItem(node, node._shape.fNode.fLeft, 'Left'); + JSROOT.GEO.createItem(node, node._shape.fNode.fRight, 'Right'); + return true; + } + } + + if (!sub._title && (obj._typename != "TGeoVolume")) sub._title = obj._typename; + + if (shape) { + if (sub._title == "") + sub._title = shape._typename; + + sub._icon = JSROOT.GEO.getShapeIcon(shape); + } else { + sub._icon = sub._more ? "img_geocombi" : "img_geobbox"; + } + + if (volume) + sub._icon += JSROOT.GEO.provideVisStyle(volume); + + sub._menu = JSROOT.GEO.provideMenu; + sub._icon_click = JSROOT.GEO.browserIconClick; + + } + + if (!node._childs) node._childs = []; + node._childs.push(sub); + + return sub; + } + + JSROOT.GEO.createList = function(parent, lst, name, title) { + + if ((lst==null) || !('arr' in lst) || (lst.arr.length==0)) return; + + var item = { + _name: name, + _kind: "Folder", + _title: title, + _more: true, + _geoobj: lst, + _parent: parent, + } + + item._get = function(item, itemname, callback) { + if ('_geoobj' in item) + return JSROOT.CallBack(callback, item, item._geoobj); + + JSROOT.CallBack(callback, item, null); + } + + item._expand = function(node, lst) { + // only childs + + if ('fVolume' in lst) + lst = lst.fVolume.fNodes; + + if (!('arr' in lst)) return false; + + node._childs = []; + + for (var n in lst.arr) + JSROOT.GEO.createItem(node, lst.arr[n]); + + return true; + } + + if (!parent._childs) parent._childs = []; + parent._childs.push(item); + + }; + + JSROOT.GEO.provideMenu = function(menu, item, hpainter) { + + if (!item._volume || !item._geoobj) return false; + + menu.add("separator"); + var vol = item._volume; + + function ToggleMenuBit(arg) { + JSROOT.GEO.ToggleBit(vol, arg); + var newname = item._icon.split(" ")[0] + JSROOT.GEO.provideVisStyle(vol); + hpainter.ForEach(function(m) { + // update all items with that volume + if (item._volume === m._volume) { + m._icon = newname; + hpainter.UpdateTreeNode(m); + } + }); + + hpainter.UpdateTreeNode(item); + JSROOT.GEO.findItemWithPainter(item, 'testGeomChanges'); + } + + + if ((item._geoobj._typename.indexOf("TGeoNode")===0) && JSROOT.GEO.findItemWithPainter(item)) + menu.add("Focus", function() { + + var drawitem = JSROOT.GEO.findItemWithPainter(item); + // console.log(drawitem); + if (!drawitem) return; + + var fullname = hpainter.itemFullName(item, drawitem); + if (drawitem._painter && typeof drawitem._painter.focusOnItem == 'function') + drawitem._painter.focusOnItem(fullname); + }); + + menu.addchk(JSROOT.GEO.TestBit(vol, JSROOT.GEO.BITS.kVisNone), "Invisible", + JSROOT.GEO.BITS.kVisNone, ToggleMenuBit); + menu.addchk(JSROOT.GEO.TestBit(vol, JSROOT.GEO.BITS.kVisThis), "Visible", + JSROOT.GEO.BITS.kVisThis, ToggleMenuBit); + menu.addchk(JSROOT.GEO.TestBit(vol, JSROOT.GEO.BITS.kVisDaughters), "Daughters", + JSROOT.GEO.BITS.kVisDaughters, ToggleMenuBit); + menu.addchk(JSROOT.GEO.TestBit(vol, JSROOT.GEO.BITS.kVisOneLevel), "1lvl daughters", + JSROOT.GEO.BITS.kVisOneLevel, ToggleMenuBit); + + return true; + } + + JSROOT.GEO.findItemWithPainter = function(hitem, funcname) { + while (hitem) { + if (hitem._painter && hitem._painter._camera) { + if (funcname && typeof hitem._painter[funcname] == 'function') + hitem._painter[funcname](); + return hitem; + } + hitem = hitem._parent; + } + return null; + } + + JSROOT.GEO.updateBrowserIcons = function(volume, hpainter) { + if (!volume || !hpainter) return; + + hpainter.ForEach(function(m) { + // update all items with that volume + if (volume === m._volume) { + m._icon = m._icon.split(" ")[0] + JSROOT.GEO.provideVisStyle(volume); + hpainter.UpdateTreeNode(m); + } + }); + } + + JSROOT.GEO.browserIconClick = function(hitem, hpainter) { + if (!hitem._volume) return false; + + if (hitem._more && hitem._volume.fNodes && (hitem._volume.fNodes.arr.length>0)) + JSROOT.GEO.ToggleBit(hitem._volume, JSROOT.GEO.BITS.kVisDaughters); + else + JSROOT.GEO.ToggleBit(hitem._volume, JSROOT.GEO.BITS.kVisThis); + + JSROOT.GEO.updateBrowserIcons(hitem._volume, hpainter); + + JSROOT.GEO.findItemWithPainter(hitem, 'testGeomChanges'); + return false; // no need to update icon - we did it ourself + } + + JSROOT.GEO.getShapeIcon = function(shape) { + switch (shape._typename) { + case "TGeoArb8" : return "img_geoarb8"; break; + case "TGeoCone" : return "img_geocone"; break; + case "TGeoConeSeg" : return "img_geoconeseg"; break; + case "TGeoCompositeShape" : return "img_geocomposite"; break; + case "TGeoTube" : return "img_geotube"; break; + case "TGeoTubeSeg" : return "img_geotubeseg"; break; + case "TGeoPara" : return "img_geopara"; break; + case "TGeoParaboloid" : return "img_geoparab"; break; + case "TGeoPcon" : return "img_geopcon"; break; + case "TGeoPgon" : return "img_geopgon"; break; + case "TGeoShapeAssembly" : return "img_geoassembly"; break; + case "TGeoSphere" : return "img_geosphere"; break; + case "TGeoTorus" : return "img_geotorus"; break; + case "TGeoTrd1" : return "img_geotrd1"; break; + case "TGeoTrd2" : return "img_geotrd2"; break; + case "TGeoXtru" : return "img_geoxtru"; break; + case "TGeoTrap" : return "img_geotrap"; break; + case "TGeoGtra" : return "img_geogtra"; break; + case "TGeoEltu" : return "img_geoeltu"; break; + case "TGeoHype" : return "img_geohype"; break; + case "TGeoCtub" : return "img_geoctub"; break; + } + return "img_geotube"; + } + + JSROOT.GEO.expandObject = function(parent, obj) { + if (!parent || !obj) return false; + + var isnode = (obj._typename.indexOf('TGeoNode') === 0), + isvolume = (obj._typename.indexOf('TGeoVolume') === 0), + ismanager = (obj._typename === 'TGeoManager'), + iseve = (obj._typename === 'TEveGeoShapeExtract'); + + if (!isnode && !isvolume && !ismanager && !iseve) return false; + + if (parent._childs) return true; + + // if (!parent._childs) parent._childs = []; + var volume, subnodes, shape; + + if (iseve) { + // volume = obj; + subnodes = obj.fElements ? obj.fElements.arr : null; + shape = obj.fShape; + } else { + volume = ismanager ? obj.fMasterVolume : (isnode ? obj.fVolume : obj); + subnodes = volume && volume.fNodes ? volume.fNodes.arr : null; + shape = volume ? volume.fShape : null; + } + + if (ismanager || (!parent._geoobj && subnodes && subnodes.length && !iseve)) { + if (ismanager) { + JSROOT.GEO.createList(parent, obj.fMaterials, "Materials", "list of materials"); + JSROOT.GEO.createList(parent, obj.fMedia, "Media", "list of media"); + JSROOT.GEO.createList(parent, obj.fTracks, "Tracks", "list of tracks"); + } + + if (volume) { + JSROOT.GEO.createItem(parent, volume, "Volumes"); + JSROOT.GEO.createList(parent, volume.fNodes, "Nodes", "Hierarchy of TGeoNodes"); + } + + return true; + } + + if (!subnodes && shape && (shape._typename === "TGeoCompositeShape") && shape.fNode) { + if (!parent._childs) { + JSROOT.GEO.createItem(parent, shape.fNode.fLeft, 'Left'); + JSROOT.GEO.createItem(parent, shape.fNode.fRight, 'Right'); + } + + return true; + } + + if (!subnodes) return false; + + var map = []; + + for (var i=0;i=0)&&(h0){for(var e=0;e0)?("/"+d[e]):"")}}if(a.hpainter){if(a.hpainter.nobrowser&&c){a.hpainter.ToggleFloatBrowser(true)}a.hpainter.actiavte(d,c);if(!this.options.update_browser){setTimeout(function(){a.hpainter.actiavte([])},2000)}}};a.TGeoPainter.prototype.TestMatrixes=function(){var e=this,g=0,d=0,h=0;var c={domatrix:true,func:function(j){var p=this.getmatrix();var o=this.CopyStack();var r=e._clones.CreateObject3D(o.stack,e._toplevel,"mesh");if(!r){return true}d++;var q=r.matrixWorld,m,i;if(q.equals(p)){return true}if((q.determinant()>0)&&(p.determinant()<-0.9)){m=THREE.Vector3(1,1,-1);i=p;p=p.clone().scale(m);if(q.equals(p)){return true}}var n=0;for(var l=0;l<16;++l){n=Math.max(n,Math.abs(q.elements[l]-p.elements[l]))}h=Math.max(n,h);if(n<0.0001){return true}console.log(e._clones.ResolveStack(o.stack).name,"maxdiff",n,"determ",q.determinant(),p.determinant());g++;return false}};tm1=new Date().getTime();var f=this._clones.ScanVisible(c);tm2=new Date().getTime();console.log("Compare matrixes total",d,"errors",g,"takes",tm2-tm1,"maxdiff",h)};a.TGeoPainter.prototype.FillContextMenu=function(c){c.add("header: Draw options");c.addchk(this.options.update_browser,"Browser update",function(){this.options.update_browser=!this.options.update_browser;if(!this.options.update_browser){this.ActiavteInBrowser([])}});c.addchk(this.options.show_controls,"Show Controls",function(){this.options.show_controls=!this.options.show_controls;this.showControlOptions(this.options.show_controls)});c.addchk(this.TestAxisVisibility,"Show axes",function(){this.toggleAxisDraw()});c.addchk(this.options.wireframe,"Wire frame",function(){this.options.wireframe=!this.options.wireframe;this.changeWireFrame(this._scene,this.options.wireframe)});c.addchk(this.options.highlight,"Highlight volumes",function(){this.options.highlight=!this.options.highlight});c.addchk(this.options.wireframe,"Reset camera position",function(){this.focusCamera();this.Render3D()});c.addchk(this._controls.autoRotate,"Autorotate",function(){this._controls.autoRotate=!this._controls.autoRotate;this.autorotate(2.5)});c.addchk(this.options.select_in_view,"Select in view",function(){this.options.select_in_view=!this.options.select_in_view;if(this.options.select_in_view){this.startDrawGeometry()}})};a.TGeoPainter.prototype.showControlOptions=function(g){if(this._datgui){if(g){return}this._datgui.destroy();delete this._datgui;return}if(!g){return}var l=this;this._datgui=new dat.GUI({width:Math.min(650,l._renderer.domElement.width/2)});var c=new THREE.Box3().setFromObject(this._toplevel);c.expandByVector(c.size().multiplyScalar(0.01));var e=this._datgui.addFolder("Clipping");var j=e.add(this,"enableX").name("Enable X").listen();j.onChange(function(o){l.enableX=o;l._enableSSAO=o?false:l._enableSSAO;l.updateClipping()});if(this.clipX===0){this.clipX=(c.min.x+c.max.x)/2}var m=e.add(this,"clipX",c.min.x,c.max.x).name("X Position");m.onChange(function(o){l.clipX=o;if(l.enableX){l.updateClipping()}});var i=e.add(this,"enableY").name("Enable Y").listen();i.onChange(function(o){l.enableY=o;l._enableSSAO=o?false:l._enableSSAO;l.updateClipping()});if(this.clipY===0){this.clipY=(c.min.y+c.max.y)/2}var k=e.add(this,"clipY",c.min.y,c.max.y).name("Y Position");k.onChange(function(o){l.clipY=o;if(l.enableY){l.updateClipping()}});var f=e.add(this,"enableZ").name("Enable Z").listen();f.onChange(function(o){l.enableZ=o;l._enableSSAO=o?false:l._enableSSAO;l.updateClipping()});if(this.clipZ===0){this.clipZ=(c.min.z+c.max.z)/2}var h=e.add(this,"clipZ",c.min.z,c.max.z).name("Z Position");h.onChange(function(o){l.clipZ=o;if(l.enableZ){l.updateClipping()}});var d=this._datgui.addFolder("Appearance");if(this._webgl){d.add(this,"_enableSSAO").name("Smooth Lighting (SSAO)").onChange(function(o){l._renderer.antialias=!l._renderer.antialias;l.enableX=o?false:l.enableX;l.enableY=o?false:l.enableY;l.enableZ=o?false:l.enableZ;l.updateClipping()}).listen()}d.add(this.options,"highlight").name("Highlight Selection").onChange(function(o){if(o===false){if(l._selected.mesh!==null){l._selected.mesh.material.color=l._selected.originalColor;l.Render3D(0);l._selected.mesh=null}}});d.add(this,"globalTransparency",0,1).listen().onChange(function(o){l._toplevel.traverse(function(p){if(p instanceof THREE.Mesh){if(p.material.alwaysTransparent!==undefined){if(!p.material.alwaysTransparent){p.material.transparent=o!==1}p.material.opacity=Math.min(o*o,p.material.inherentOpacity)}}});l.Render3D(0)});d.add(this.options,"wireframe").name("Wireframe").onChange(function(o){l.changeWireFrame(l._scene,l.options.wireframe)});d.add(this,"focusCamera").name("Reset camera position");if(this._webgl){var n=this._datgui.addFolder("Advanced");n.add(this._advceOptions,"aoClamp",0,1).listen().onChange(function(o){l._ssaoPass.uniforms.aoClamp.value=o;l._enableSSAO=true;l.Render3D(0)});n.add(this._advceOptions,"lumInfluence",0,1).listen().onChange(function(o){l._ssaoPass.uniforms.lumInfluence.value=o;l._enableSSAO=true;l.Render3D(0)});n.add(this._advceOptions,"clipIntersection").listen().onChange(function(o){l._renderer.clipIntersection=o;l.Render3D(0)});n.add(this._advceOptions,"depthTest").onChange(function(o){l._toplevel.traverse(function(p){if(p instanceof THREE.Mesh){p.material.depthTest=o}});l.Render3D(0)}).listen();n.add(this,"resetAdvanced").name("Reset")}};a.TGeoPainter.prototype.OrbitContext=function(e,d){var c=this;a.Painter.createMenu(function(i){i.painter=c;if(!d||(d.length==0)){c.FillContextMenu(i)}else{var l=(d.length>1);if(l){i.add("header: Nodes")}for(var k=0;k0){j=g}else{if(c.GetItemName()){j=c.GetItemName()}}}i.add((l?"sub:":"header:")+j,g,function(m){this.ActiavteInBrowser([m],true)});i.add("Browse",g,function(m){this.ActiavteInBrowser([m],true)});var f=c.accessObjectWireFrame(h);if(f!==undefined){i.addchk(f,"Wireframe",k,function(o){var n=d[o].object.material;n.wireframe=!n.wireframe;this.Render3D()})}if(k>0){i.add("Manifest",k,function(n){if(this._last_manifest){this._last_manifest.wireframe=!this._last_manifest.wireframe}if(this._last_hidden){this._last_hidden.forEach(function(o){o.visible=true})}this._last_hidden=[];for(var m=0;m=0;--l){var j=h[l].object.stack!==undefined;for(var e=0;(ethis._clipPlanes[0].constant){d=true}if(this.enableY&&this._clipPlanes[1].normal.dot(c)>this._clipPlanes[1].constant){d=true}if(this.enableZ&&this._clipPlanes[2].normal.dot(c)>this._clipPlanes[2].constant){d=true}if(d){g.push(h[f])}}h=g}return h};a.TGeoPainter.prototype.testCameraPositionChange=function(){if(!this.options.select_in_view||this._draw_all_nodes){return}var c=a.GEO.CreateProjectionMatrix(this._camera);var d=a.GEO.CreateFrustum(c);if(!d.CheckBox(new THREE.Box3().setFromObject(this._toplevel))){this.startDrawGeometry()}};a.TGeoPainter.prototype.addOrbitControls=function(){if(this._controls){return}this.select_main().property("flex_block_drag",true);var c=this;this._controls=a.Painter.CreateOrbitControl(this,this._camera,this._scene,this._renderer,this._lookat);this._controls.ContextMenu=this.OrbitContext.bind(this);this._controls.ProcessMouseMove=function(d){var e=null;if(c.options.highlight){if(c._selected.mesh!==null){c._selected.mesh.material.color=c._selected.originalColor}if(d.length>0){c._selected.mesh=d[0].object;c._selected.originalColor=c._selected.mesh.material.color;c._selected.mesh.material.color=new THREE.Color(16755251);c.Render3D(0);if(d[0].object.stack){e=c._clones.ResolveStack(d[0].object.stack).name}}}if(d.length===0&&c._selected.mesh!==null){c._selected.mesh.material.color=c._selected.originalColor;c.Render3D(0);c._selected.mesh=null}var g=[];if(c.options.update_browser){if(c.options.highlight){if(e!==null){g.push(e)}}else{for(var h=0;h0){if(!this._worker){this.startWorker();return 1}if(!this._worker_ready){return 1}}var o=this._clones.MarkVisisble(),t=null,m=null;if(this.options.select_in_view&&!this._first_drawing){t=a.GEO.CreateProjectionMatrix(this._camera);m=a.GEO.CreateFrustum(t);if(m.CheckBox(new THREE.Box3().setFromObject(this._toplevel))){t=null;m=null}}this._current_face_limit=this.options.maxlimit;if(t){this._current_face_limit*=1.25}var q=(o>10000)||(t&&(this._clones.ScanVisible()>100000));if(q&&!this._worker&&(this.options.use_worker>=0)){this.startWorker()}if(!q||!this._worker_ready){var z=this._clones.CollectVisibles(this._current_face_limit,m);this._new_draw_nodes=z.lst;this._draw_all_nodes=z.complete;this.drawing_stage=3;return true}var k={collect:this._current_face_limit,visible:this._clones.GetVisibleFlags(),matrix:t?t.elements:null};this.submitToWorker(k);this.drawing_stage=2;this.drawing_log="Worker select visibles";return 2}if(this.drawing_stage==2){this.drawing_log="Worker select visibles";return 2}if(this.drawing_stage==3){this.drawing_log="Analyse visibles";if(this._draw_nodes){var l=this._clones.MergeVisibles(this._new_draw_nodes,this._draw_nodes);for(var s=0;s0){this.drawing_log="Delete "+l.length+" nodes"}}this._draw_nodes=this._new_draw_nodes;delete this._new_draw_nodes;this.drawing_stage=4;return true}if(this.drawing_stage===4){this.drawing_log="Collect shapes";var r=this._clones.CollectShapes(this._draw_nodes);this._build_shapes=this._clones.MergeShapesLists(this._build_shapes,r);this.drawing_stage=5;return true}if(this.drawing_stage===5){if(this.canSubmitToWorker()){var k={limit:this._current_face_limit,shapes:[]},u=0;for(var s=0;s0){this.submitToWorker(k);this.drawing_log="Worker build shapes";this.drawing_stage=6;return 2}}this.drawing_stage=7}if(this.drawing_stage===6){return 2}if((this.drawing_stage===7)||(this.drawing_stage===8)){if(this.drawing_stage===7){var z=this._clones.BuildShapes(this._build_shapes,this._current_face_limit,500);if(z.done){this.drawing_stage=8}else{this.drawing_log="Creating: "+z.shapes+" / "+this._build_shapes.length+" shapes, "+z.faces+" faces";if(z.notusedshapes<30){return true}}}var i=new Date().getTime(),p=true;for(var s=0;s-0.9){d=new THREE.Mesh(e.geom,g.material)}else{d=this.createFlippedMesh(y,e,g.material)}d.stack=f.stack;y.add(d);if(this.options._debug||this.options._full){var c=new THREE.WireframeHelper(d);c.material.color.set(g.fillcolor);c.material.linewidth=("fVolume" in j)?j.fVolume.fLineWidth:1;y.add(c)}if(this.options._bound||this.options._full){var v=new THREE.BoxHelper(d);y.add(v)}var h=new Date().getTime();if(h-i>500){p=false;break}}if(p){this.drawing_log="Building done";this.drawing_stage=0;return false}if(this.drawing_stage>7){this.drawing_log="Building meshes "+this._num_meshes+" / "+this._num_faces}return true}console.log("never come here");return false};a.TGeoPainter.prototype.SameMaterial=function(e,c){if((e===null)||(c===null)){return e===c}if(e.fVolume.fLineColor>=0){return(e.fVolume.fLineColor===c.fVolume.fLineColor)}var f=(e.fVolume.fMedium!==null)?e.fVolume.fMedium.fMaterial:null;var d=(c.fVolume.fMedium!==null)?c.fVolume.fMedium.fMaterial:null;if(f===d){return true}if((f===null)||(d===null)){return false}return(f.fFillStyle===d.fFillStyle)&&(f.fFillColor===d.fFillColor)};a.TGeoPainter.prototype.createScene=function(i,c,f,e){this._scene=new THREE.Scene();this._scene.fog=new THREE.Fog(16777215,1,10000);this._scene.overrideMaterial=new THREE.MeshLambertMaterial({color:7340287,transparent:true,opacity:0.2,depthTest:false});this._scene_width=c;this._scene_height=f;this._camera=new THREE.PerspectiveCamera(25,c/f,1,10000);this._camera.up=this.options._yup?new THREE.Vector3(0,1,0):new THREE.Vector3(0,0,1);this._scene.add(this._camera);this._selected={mesh:null,originalColor:null};this._overall_size=10;this._toplevel=new THREE.Object3D();this._scene.add(this._toplevel);this._renderer=i?new THREE.WebGLRenderer({antialias:true,logarithmicDepthBuffer:false,preserveDrawingBuffer:true}):new THREE.CanvasRenderer({antialias:true});this._renderer.setPixelRatio(e);this._renderer.setClearColor(16777215,1);this._renderer.setSize(c,f);this._renderer.clipIntersection=true;this._animating=false;this.bothSides=false;this.enableX=this.enableY=this.enableZ=false;this.clipX=this.clipY=this.clipZ=0;this._clipPlanes=[new THREE.Plane(new THREE.Vector3(1,0,0),this.clipX),new THREE.Plane(new THREE.Vector3(0,this.options._yup?-1:1,0),this.clipY),new THREE.Plane(new THREE.Vector3(0,0,this.options._yup?1:-1),this.clipZ)];this._pointLight=new THREE.PointLight(15724527,1);this._camera.add(this._pointLight);this._pointLight.position.set(10,10,10);this.globalTransparency=1;this._defaultAdvanced={aoClamp:0.7,lumInfluence:0.4,clipIntersection:true,depthTest:true};this._enableSSAO=false;if(i){var g=new THREE.RenderPass(this._scene,this._camera);this._depthMaterial=new THREE.MeshDepthMaterial({side:THREE.DoubleSide});this._depthMaterial.depthPacking=THREE.RGBADepthPacking;this._depthMaterial.blending=THREE.NoBlending;var d={minFilter:THREE.LinearFilter,magFilter:THREE.LinearFilter};this._depthRenderTarget=new THREE.WebGLRenderTarget(c,f,d);this._ssaoPass=new THREE.ShaderPass(THREE.SSAOShader);this._ssaoPass.renderToScreen=true;this._ssaoPass.uniforms.tDepth.value=this._depthRenderTarget.texture;this._ssaoPass.uniforms.size.value.set(c,f);this._ssaoPass.uniforms.cameraNear.value=this._camera.near;this._ssaoPass.uniforms.cameraFar.value=this._camera.far;this._ssaoPass.uniforms.onlyAO.value=false;this._ssaoPass.uniforms.aoClamp.value=this._defaultAdvanced.aoClamp;this._ssaoPass.uniforms.lumInfluence.value=this._defaultAdvanced.lumInfluence;this._effectComposer=new THREE.EffectComposer(this._renderer);this._effectComposer.addPass(g);this._effectComposer.addPass(this._ssaoPass)}this._advceOptions={};this.resetAdvanced()};a.TGeoPainter.prototype.startDrawGeometry=function(c){if(!c&&(this.drawing_stage!==0)){this._draw_nodes_again=true;return}this._startm=new Date().getTime();this._last_render_tm=this._startm;this._last_render_meshes=0;this.drawing_stage=1;this.drawing_log="collect visible";this._num_meshes=0;this._num_faces=0;delete this._last_manifest;delete this._last_hidden;delete this._draw_nodes_again;this.continueDraw()};a.TGeoPainter.prototype.resetAdvanced=function(){if(this._webgl){this._advceOptions.aoClamp=this._defaultAdvanced.aoClamp;this._advceOptions.lumInfluence=this._defaultAdvanced.lumInfluence;this._ssaoPass.uniforms.aoClamp.value=this._defaultAdvanced.aoClamp;this._ssaoPass.uniforms.lumInfluence.value=this._defaultAdvanced.lumInfluence}this._advceOptions.depthTest=this._defaultAdvanced.depthTest;this._advceOptions.clipIntersection=this._defaultAdvanced.clipIntersection;this._renderer.clipIntersection=this._defaultAdvanced.clipIntersection;var c=this;this._toplevel.traverse(function(d){if(d instanceof THREE.Mesh){d.material.depthTest=c._defaultAdvanced.depthTest}});this.Render3D(0)};a.TGeoPainter.prototype.updateMaterialSide=function(c,d){if((this.bothSides===c)&&!d){return}this._scene.traverse(function(e){if(e.hasOwnProperty("material")&&("emissive" in e.material)){e.material.side=c?THREE.DoubleSide:THREE.FrontSide;e.material.needsUpdate=true}});this.bothSides=c};a.TGeoPainter.prototype.updateClipping=function(c){this._clipPlanes[0].constant=this.clipX;this._clipPlanes[1].constant=-this.clipY;this._clipPlanes[2].constant=this.options._yup?-this.clipZ:this.clipZ;this._renderer.clippingPlanes=[];if(this.enableX){this._renderer.clippingPlanes.push(this._clipPlanes[0])}if(this.enableY){this._renderer.clippingPlanes.push(this._clipPlanes[1])}if(this.enableZ){this._renderer.clippingPlanes.push(this._clipPlanes[2])}this.updateMaterialSide(this.enableX||this.enableY||this.enableZ);if(!c){this.Render3D(0)}};a.TGeoPainter.prototype.adjustCameraPosition=function(i){var h=new THREE.Box3().setFromObject(this._toplevel);var e=h.max.x-h.min.x,c=h.max.y-h.min.y,j=h.max.z-h.min.z,g=(h.max.x+h.min.x)/2,f=(h.max.y+h.min.y)/2,d=(h.max.z+h.min.z)/2;this._overall_size=2*Math.max(e,c,j);this._scene.fog.near=this._overall_size*2;this._camera.near=this._overall_size/350;this._scene.fog.far=this._overall_size*12;this._camera.far=this._overall_size*12;if(this._webgl){this._ssaoPass.uniforms.cameraNear.value=this._camera.near;this._ssaoPass.uniforms.cameraFar.value=this._camera.far}if(i){this.clipX=g;this.clipY=f;this.clipZ=d}this._camera.updateProjectionMatrix();if(this.options._yup){this._camera.position.set(g-2*Math.max(e,j),f+2*c,d-2*Math.max(e,j))}else{this._camera.position.set(g-2*Math.max(e,c),f-2*Math.max(e,c),d+2*j)}this._lookat=new THREE.Vector3(g,f,d);this._camera.lookAt(this._lookat);this._pointLight.position.set(e/5,c/5,j/5);if(this._controls){this._controls.target.copy(this._lookat);this._controls.update()}if(this.options.select_in_view){this.startDrawGeometry()}};a.TGeoPainter.prototype.focusOnItem=function(e){if(!e||(e.indexOf("Nodes/")!==0)||!this._clones){return}var c=this._clones.FindStackByName(e.substr(6));if(!c){return}var d=this._clones.ResolveStack(c,true);this.focusCamera(d,false)};a.TGeoPainter.prototype.focusCamera=function(m,v){var q=v===undefined?false:v;var k=new THREE.Box3();if(m===undefined){k.setFromObject(this._toplevel)}else{if(m instanceof THREE.Mesh){k.setFromObject(m)}else{var A=new THREE.Vector3().setFromMatrixPosition(m.matrix);var p=m.node;var n=new THREE.Vector3(p.fDX,p.fDY,p.fDZ).multiplyScalar(0.5);k.min=A.clone().sub(n);k.max=A.clone().add(n)}}var z=k.max.x-k.min.x,x=k.max.y-k.min.y,w=k.max.z-k.min.z,u=(k.max.x+k.min.x)/2,t=(k.max.y+k.min.y)/2,r=(k.max.z+k.min.z)/2;var C;if(this.options._yup){C=new THREE.Vector3(u-2*Math.max(z,w),t+2*x,r-2*Math.max(z,w))}else{C=new THREE.Vector3(u-2*Math.max(z,x),t-2*Math.max(z,x),r+2*w)}var B=new THREE.Vector3(u,t,r);var o=this._camera.position.distanceTo(B);var s=this._controls.target;var l=200;var i=0;var f=C.sub(this._camera.position).divideScalar(l);var j=B.sub(s).divideScalar(l);console.log(j);if(q){var g=new THREE.Box3().setFromObject(this._toplevel);this.clipX=this.enableX?this.clipX:g.min.x;this.clipY=this.enableY?this.clipY:g.min.y;this.clipZ=this.enableZ?this.clipZ:g.min.z;this.enableX=this.enableY=this.enableZ=true;var e=((k.max.x+k.min.x)/2-this.clipX)/l,d=((k.max.y+k.min.y)/2-this.clipY)/l,c=((k.max.z+k.min.z)/2-this.clipZ)/l;this.updateClipping()}var y=this;this._animating=true;this._controls.autoRotate=false;function h(){if(y._animating){requestAnimationFrame(h)}else{y.startDrawGeometry()}var D=-Math.cos((2*Math.PI*i)/l)+1;y._camera.position.add(f.clone().multiplyScalar(D));s.add(j.clone().multiplyScalar(D));y._lookat=s;y._camera.lookAt(y._lookat);y._camera.updateProjectionMatrix();if(q){y.clipX+=e*D;y.clipY+=d*D;y.clipZ+=c*D;y.updateClipping()}else{y.Render3D()}i++;y._animating=i
Transform Controls
'T' translate | 'R' rotate | 'S' scale
'+' increase size | '-' decrease size
'W' toggle wireframe/solid display
keep 'Ctrl' down to snap to grid
")}};a.TGeoPainter.prototype.drawCount=function(k,g){var h="Unique nodes: "+this._clones.nodes.length+"
Unique visible: "+k+"
Time to clone: "+g+"ms
";this._clones.ScanVisible();var l={cnt:[],func:function(m){if(this.cnt[this.last]===undefined){this.cnt[this.last]=1}else{this.cnt[this.last]++}return true}};var d=new Date().getTime();var f=this._clones.ScanVisible(l);var c=new Date().getTime();h+="Total visible nodes: "+f+"
";for(var i=0;i")}}h+="Time to scan: "+(c-d)+"ms
";h+="

Check timing for matrix calculations ...
";var e=this.select_main().style("overflow","auto").html(h);var j=this;setTimeout(function(){l.domatrix=true;d=new Date().getTime();f=j._clones.ScanVisible(l);c=new Date().getTime();e.append("p").text("Time to scan with matrix: "+(c-d)+"ms")},100);return this.DrawingReady()};a.TGeoPainter.prototype.DrawGeometry=function(f){if(typeof f!=="string"){f=""}var e=this.size_for_3d();this._webgl=a.Painter.TestWebGL();this.options=this.decodeOptions(f);if(!("_yup" in this.options)){this.options._yup=this.svg_canvas().empty()}var d=new Date().getTime();this._clones=new a.GEO.ClonedNodes(this.GetObject());var g=this._clones.MarkVisisble(true);if(g<=0){g=this._clones.MarkVisisble(false)}else{g=this._clones.MarkVisisble(true,true)}var c=new Date().getTime();console.log("Creating clones",this._clones.nodes.length,"takes",c-d,"uniquevis",g);if(this.options._count){return this.drawCount(g,c-d)}this.options.maxlimit=(this._webgl?200000:100000)*this.options.more;this._first_drawing=true;if(this.options.use_worker>0){this.startWorker()}this.createScene(this._webgl,e.width,e.height,window.devicePixelRatio);this.add_3d_canvas(e,this._renderer.domElement);this.CreateToolbar();this.startDrawGeometry(true);return this};a.TGeoPainter.prototype.continueDraw=function(){if(this.drawing_stage===0){return}var d=new Date().getTime(),c=this._first_drawing?1000:200,e=d;while(true){var f=this.nextDrawAction();if(!f){break}e=new Date().getTime();if(e-this._startm>100000){this.drawing_stage=0;break}if((f===true)&&(e-dc)||(f===1)||(f===2)){a.progress(this.drawing_log);if(this._first_drawing&&this._webgl&&(this._num_meshes-this._last_render_meshes>100)&&(e-this._last_render_tm>2.5*c)){this.adjustCameraPosition();this.Render3D(-1);this._last_render_tm=new Date().getTime();this._last_render_meshes=this._num_meshes}if(f!==2){setTimeout(this.continueDraw.bind(this),(f===1)?100:1)}return}}var g=e-this._startm;if(this._first_drawing){a.console("Create tm = "+g+" meshes "+this._num_meshes+" faces "+this._num_faces)}if(g>300){a.progress("Rendering geometry");return setTimeout(this.completeDraw.bind(this,true),10)}this.completeDraw(true)};a.TGeoPainter.prototype.Render3D=function(f,e){if(f===undefined){f=5}if(f<=0){if("render_tmout" in this){clearTimeout(this.render_tmout)}var d=new Date();if(typeof this.TestAxisVisibility==="function"){this.TestAxisVisibility(this._camera,this._toplevel)}if(this._webgl&&this._enableSSAO){this._scene.overrideMaterial=this._depthMaterial;this._renderer.render(this._scene,this._camera,this._depthRenderTarget,true);this._scene.overrideMaterial=null;this._effectComposer.render()}else{this._renderer.render(this._scene,this._camera)}var c=new Date();this.last_render_tm=c.getTime()-d.getTime();delete this.render_tmout;if((this.first_render_tm===0)&&e){this.first_render_tm=this.last_render_tm;a.console("First render tm = "+this.first_render_tm)}return}if(!this.render_tmout){this.render_tmout=setTimeout(this.Render3D.bind(this,0,e),f)}};a.TGeoPainter.prototype.startWorker=function(){if(this._worker){return}this._worker_ready=false;this._worker_jobs=0;var c=this;this._worker=new Worker(a.source_dir+"scripts/JSRootGeoWorker.js");this._worker.onmessage=function(d){if(typeof d.data!=="object"){return}if("log" in d.data){return a.console("geo: "+d.data.log)}if("progress" in d.data){return a.progress(d.data.progress)}d.data.tm3=new Date().getTime();if("init" in d.data){c._worker_ready=true;return a.console("Worker ready: "+(d.data.tm3-d.data.tm0))}c.processWorkerReply(d.data)};this._worker.postMessage({init:true,tm0:new Date().getTime(),clones:this._clones.nodes,sortmap:this._clones.sortmap})};a.TGeoPainter.prototype.canSubmitToWorker=function(c){if(!this._worker){return false}return this._worker_ready&&((this._worker_jobs==0)||c)};a.TGeoPainter.prototype.submitToWorker=function(c){if(!this._worker){return false}this._worker_jobs++;c.tm0=new Date().getTime();this._worker.postMessage(c)};a.TGeoPainter.prototype.processWorkerReply=function(e){this._worker_jobs--;if("collect" in e){this._new_draw_nodes=e.new_nodes;this._draw_all_nodes=e.complete;this.drawing_stage=3;return this.continueDraw()}if("shapes" in e){for(var f=0;f0){e._title+=" "+i.fTitle}f=i.fVolume}else{if(i._typename.indexOf("TGeoVolume")===0){f=i}else{if(i._typename=="TEveGeoShapeExtract"){c=i.fShape;h=i.fElements?i.fElements.arr:null}else{if((i.fShapeBits!==undefined)&&(i.fShapeId!==undefined)){c=i}}}}}}}if(f){c=f.fShape;h=f.fNodes?f.fNodes.arr:null}if(f||c||h){if(f){e._volume=f}if(h){e._more=true;e._expand=a.GEO.expandObject}else{if(c&&(c._typename==="TGeoCompositeShape")&&c.fNode){e._more=true;e._shape=c;e._expand=function(j,k){a.GEO.createItem(j,j._shape.fNode.fLeft,"Left");a.GEO.createItem(j,j._shape.fNode.fRight,"Right");return true}}}if(!e._title&&(i._typename!="TGeoVolume")){e._title=i._typename}if(c){if(e._title==""){e._title=c._typename}e._icon=a.GEO.getShapeIcon(c)}else{e._icon=e._more?"img_geocombi":"img_geobbox"}if(f){e._icon+=a.GEO.provideVisStyle(f)}e._menu=a.GEO.provideMenu;e._icon_click=a.GEO.browserIconClick}if(!g._childs){g._childs=[]}g._childs.push(e);return e};a.GEO.createList=function(e,c,d,g){if((c==null)||!("arr" in c)||(c.arr.length==0)){return}var f={_name:d,_kind:"Folder",_title:g,_more:true,_geoobj:c,_parent:e};f._get=function(h,j,i){if("_geoobj" in h){return a.CallBack(i,h,h._geoobj)}a.CallBack(i,h,null)};f._expand=function(i,h){if("fVolume" in h){h=h.fVolume.fNodes}if(!("arr" in h)){return false}i._childs=[];for(var j in h.arr){a.GEO.createItem(i,h.arr[j])}return true};if(!e._childs){e._childs=[]}e._childs.push(f)};a.GEO.provideMenu=function(g,d,e){if(!d._volume||!d._geoobj){return false}g.add("separator");var c=d._volume;function f(h){a.GEO.ToggleBit(c,h);var i=d._icon.split(" ")[0]+a.GEO.provideVisStyle(c);e.ForEach(function(j){if(d._volume===j._volume){j._icon=i;e.UpdateTreeNode(j)}});e.UpdateTreeNode(d);a.GEO.findItemWithPainter(d,"testGeomChanges")}if((d._geoobj._typename.indexOf("TGeoNode")===0)&&a.GEO.findItemWithPainter(d)){g.add("Focus",function(){var i=a.GEO.findItemWithPainter(d);if(!i){return}var h=e.itemFullName(d,i);if(i._painter&&typeof i._painter.focusOnItem=="function"){i._painter.focusOnItem(h)}})}g.addchk(a.GEO.TestBit(c,a.GEO.BITS.kVisNone),"Invisible",a.GEO.BITS.kVisNone,f);g.addchk(a.GEO.TestBit(c,a.GEO.BITS.kVisThis),"Visible",a.GEO.BITS.kVisThis,f);g.addchk(a.GEO.TestBit(c,a.GEO.BITS.kVisDaughters),"Daughters",a.GEO.BITS.kVisDaughters,f);g.addchk(a.GEO.TestBit(c,a.GEO.BITS.kVisOneLevel),"1lvl daughters",a.GEO.BITS.kVisOneLevel,f);return true};a.GEO.findItemWithPainter=function(d,c){while(d){if(d._painter&&d._painter._camera){if(c&&typeof d._painter[c]=="function"){d._painter[c]()}return d}d=d._parent}return null};a.GEO.updateBrowserIcons=function(c,d){if(!c||!d){return}d.ForEach(function(e){if(c===e._volume){e._icon=e._icon.split(" ")[0]+a.GEO.provideVisStyle(c);d.UpdateTreeNode(e)}})};a.GEO.browserIconClick=function(c,d){if(!c._volume){return false}if(c._more&&c._volume.fNodes&&(c._volume.fNodes.arr.length>0)){a.GEO.ToggleBit(c._volume,a.GEO.BITS.kVisDaughters)}else{a.GEO.ToggleBit(c._volume,a.GEO.BITS.kVisThis)}a.GEO.updateBrowserIcons(c._volume,d);a.GEO.findItemWithPainter(c,"testGeomChanges");return false};a.GEO.getShapeIcon=function(c){switch(c._typename){case"TGeoArb8":return"img_geoarb8";break;case"TGeoCone":return"img_geocone";break;case"TGeoConeSeg":return"img_geoconeseg";break;case"TGeoCompositeShape":return"img_geocomposite";break;case"TGeoTube":return"img_geotube";break;case"TGeoTubeSeg":return"img_geotubeseg";break;case"TGeoPara":return"img_geopara";break;case"TGeoParaboloid":return"img_geoparab";break;case"TGeoPcon":return"img_geopcon";break;case"TGeoPgon":return"img_geopgon";break;case"TGeoShapeAssembly":return"img_geoassembly";break;case"TGeoSphere":return"img_geosphere";break;case"TGeoTorus":return"img_geotorus";break;case"TGeoTrd1":return"img_geotrd1";break;case"TGeoTrd2":return"img_geotrd2";break;case"TGeoXtru":return"img_geoxtru";break;case"TGeoTrap":return"img_geotrap";break;case"TGeoGtra":return"img_geogtra";break;case"TGeoEltu":return"img_geoeltu";break;case"TGeoHype":return"img_geohype";break;case"TGeoCtub":return"img_geoctub";break}return"img_geotube"};a.GEO.expandObject=function(o,k){if(!o||!k){return false}var l=(k._typename.indexOf("TGeoNode")===0),e=(k._typename.indexOf("TGeoVolume")===0),f=(k._typename==="TGeoManager"),h=(k._typename==="TEveGeoShapeExtract");if(!l&&!e&&!f&&!h){return false}if(o._childs){return true}var m,d,n;if(h){d=k.fElements?k.fElements.arr:null;n=k.fShape}else{m=f?k.fMasterVolume:(l?k.fVolume:k);d=m&&m.fNodes?m.fNodes.arr:null;n=m?m.fShape:null}if(f||(!o._geoobj&&d&&d.length&&!h)){if(f){a.GEO.createList(o,k.fMaterials,"Materials","list of materials");a.GEO.createList(o,k.fMedia,"Media","list of media");a.GEO.createList(o,k.fTracks,"Tracks","list of tracks")}if(m){a.GEO.createItem(o,m,"Volumes");a.GEO.createList(o,m.fNodes,"Nodes","Hierarchy of TGeoNodes")}return true}if(!d&&n&&(n._typename==="TGeoCompositeShape")&&n.fNode){if(!o._childs){a.GEO.createItem(o,n.fNode.fLeft,"Left");a.GEO.createItem(o,n.fNode.fRight,"Right")}return true}if(!d){return false}var c=[];for(var j=0;j= totallen) { + if (!noalert) alert("Error R__unzip: header size exceeds buffer size"); + return null; + } + + /* C H E C K H E A D E R */ + if (!((getChar(curr) == 'Z' && getChar(curr+1) == 'L' && getCode(curr+2) == JSROOT.IO.Z_DEFLATED))) { + if (!noalert) alert("R__unzip: Old zlib format is not supported!"); + return null; + } + + var srcsize = JSROOT.IO.Z_HDRSIZE + + ((getCode(curr+3) & 0xff) | ((getCode(curr+4) & 0xff) << 8) | ((getCode(curr+5) & 0xff) << 16)); + + if (isarr) { + // portion of packed data to process + var uint8arr = new Uint8Array(str.buffer, str.byteOffset + curr + JSROOT.IO.Z_HDRSIZE + 2, str.byteLength - curr - JSROOT.IO.Z_HDRSIZE - 2); + + // place for unpacking + if (tgtbuf===null) tgtbuf = new ArrayBuffer(tgtsize); + + var reslen = window.RawInflate.arr_inflate(uint8arr, new Uint8Array(tgtbuf, fullres)); + if (reslen<=0) break; + + fullres += reslen; + } else { + // old code using String for unpacking, keep for compativility + var unpacked = window.RawInflate.inflate(str.substr(JSROOT.IO.Z_HDRSIZE + 2 + curr, srcsize)); + if ((unpacked === null) || (unpacked.length===0)) break; + if (tgtbuf===null) tgtbuf = unpacked; else tgtbuf += unpacked; + fullres += unpacked.length; + } + + curr += srcsize; + } + + if (fullres !== tgtsize) { + if (!noalert) alert("R__unzip: fail to unzip data expacts " + tgtsize + " , got " + fullres); + return null; + } + + return isarr ? new DataView(tgtbuf) : tgtbuf; + } + + // ================================================================================= + + JSROOT.TBuffer = function(_o, _file) { + this._typename = "TBuffer"; + this.o = (_o==null) ? 0 : _o; + this.fFile = _file; + this.ClearObjectMap(); + this.fTagOffset = 0; + this.last_read_version = 0; + return this; + } + + JSROOT.TBuffer.prototype.locate = function(pos) { + this.o = pos; + } + + JSROOT.TBuffer.prototype.shift = function(cnt) { + this.o += cnt; + } + + JSROOT.TBuffer.prototype.GetMappedObject = function(tag) { + return this.fObjectMap[tag]; + } + + JSROOT.TBuffer.prototype.MapObject = function(tag, obj) { + if (obj!==null) + this.fObjectMap[tag] = obj; + } + + JSROOT.TBuffer.prototype.MapClass = function(tag, classname) { + this.fClassMap[tag] = classname; + } + + JSROOT.TBuffer.prototype.GetMappedClass = function(tag) { + if (tag in this.fClassMap) return this.fClassMap[tag]; + return -1; + } + + JSROOT.TBuffer.prototype.ClearObjectMap = function() { + this.fObjectMap = {}; + this.fClassMap = {}; + this.fObjectMap[0] = null; + } + + JSROOT.TBuffer.prototype.ReadVersion = function() { + // read class version from I/O buffer + var ver = {}; + var bytecnt = this.ntou4(); // byte count + if (bytecnt & JSROOT.IO.kByteCountMask) + ver.bytecnt = bytecnt - JSROOT.IO.kByteCountMask - 2; // one can check between Read version and end of streamer + else + this.o -= 4; // rollback read bytes, this is old buffer without bytecount + + this.last_read_version = ver.val = this.ntou2(); + ver.off = this.o; + return ver; + } + + JSROOT.TBuffer.prototype.CheckBytecount = function(ver, where) { + if (('bytecnt' in ver) && (ver.off + ver.bytecnt !== this.o)) { + if (where!=null) + alert("Missmatch in " + where + " bytecount expected = " + ver['bytecnt'] + " got = " + (this.o-ver['off'])); + this.o = ver.off + ver.bytecnt; + return false; + } + return true; + } + + JSROOT.TBuffer.prototype.ReadString = function() { + // read a null-terminated string from buffer + var pos0 = this.o, len = this.totalLength(); + while (this.o < len) { + if (this.codeAt(this.o++) == 0) break; + } + return (this.o > pos0) ? this.substring(pos0, this.o-1) : ""; + } + + JSROOT.TBuffer.prototype.ReadTString = function() { + // stream a TString object from buffer + var len = this.ntou1(); + // large strings + if (len == 255) len = this.ntou4(); + if (len==0) return ""; + + var pos = this.o; + this.o += len; + + return (this.codeAt(pos) == 0) ? '' : this.substring(pos, pos + len); + } + + JSROOT.TBuffer.prototype.ReadFastArray = function(n, array_type) { + // read array of n values from the I/O buffer + + var array = null; + switch (array_type) { + case JSROOT.IO.kDouble: + array = JSROOT.IO.NativeArray ? new Float64Array(n) : new Array(n); + for (var i = 0; i < n; ++i) + array[i] = this.ntod(); + break; + case JSROOT.IO.kFloat: + case JSROOT.IO.kDouble32: + array = JSROOT.IO.NativeArray ? new Float32Array(n) : new Array(n); + for (var i = 0; i < n; ++i) + array[i] = this.ntof(); + break; + case JSROOT.IO.kLong: + case JSROOT.IO.kLong64: + array = JSROOT.IO.NativeArray ? new Float64Array(n) : new Array(n); + for (var i = 0; i < n; ++i) + array[i] = this.ntoi8(); + break; + case JSROOT.IO.kULong: + case JSROOT.IO.kULong64: + array = JSROOT.IO.NativeArray ? new Float64Array(n) : new Array(n); + for (var i = 0; i < n; ++i) + array[i] = this.ntou8(); + break; + case JSROOT.IO.kInt: + array = JSROOT.IO.NativeArray ? new Int32Array(n) : new Array(n); + for (var i = 0; i < n; ++i) + array[i] = this.ntoi4(); + break; + case JSROOT.IO.kUInt: + array = JSROOT.IO.NativeArray ? new Uint32Array(n) : new Array(n); + for (var i = 0; i < n; ++i) + array[i] = this.ntou4(); + break; + case JSROOT.IO.kShort: + array = JSROOT.IO.NativeArray ? new Int16Array(n) : new Array(n); + for (var i = 0; i < n; ++i) + array[i] = this.ntoi2(); + break; + case JSROOT.IO.kUShort: + array = JSROOT.IO.NativeArray ? new Uint16Array(n) : new Array(n); + for (var i = 0; i < n; ++i) + array[i] = this.ntou2(); + break; + case JSROOT.IO.kChar: + array = JSROOT.IO.NativeArray ? new Int8Array(n) : new Array(n); + for (var i = 0; i < n; ++i) + array[i] = this.ntoi1(); + break; + case JSROOT.IO.kBool: + case JSROOT.IO.kUChar: + array = JSROOT.IO.NativeArray ? new Uint8Array(n) : new Array(n); + for (var i = 0; i < n; ++i) + array[i] = this.ntoi1(); + break; + case JSROOT.IO.kTString: + array = new Array(n); + for (var i = 0; i < n; ++i) + array[i] = this.ReadTString(); + break; + default: + array = new Array(n); + for (var i = 0; i < n; ++i) + array[i] = this.ntou4(); + break; + } + return array; + } + + JSROOT.IO.GetArrayKind = function(type_name) { + // returns type of array + // 0 - if TString (or equivalent) + // -1 - if any other kind + if ((type_name === "TString") || (JSROOT.fUserStreamers[type_name] === 'TString')) return 0; + if ((type_name.length < 7) || (type_name.indexOf("TArray")!==0)) return -1; + if (type_name.length == 7) + switch (type_name.charAt(6)) { + case 'I': return JSROOT.IO.kInt; + case 'D': return JSROOT.IO.kDouble; + case 'F': return JSROOT.IO.kFloat; + case 'S': return JSROOT.IO.kShort; + case 'C': return JSROOT.IO.kChar; + case 'L': return JSROOT.IO.kLong; + default: return -1; + } + + return type_name == "TArrayL64" ? JSROOT.IO.kLong64 : -1; + } + + JSROOT.TBuffer.prototype.ReadTKey = function(key) { + key.fNbytes = this.ntoi4(); + key.fVersion = this.ntoi2(); + key.fObjlen = this.ntou4(); + var datime = this.ntou4(); + key.fDatime = new Date(); + key.fDatime.setFullYear((datime >>> 26) + 1995); + key.fDatime.setMonth((datime << 6) >>> 28); + key.fDatime.setDate((datime << 10) >>> 27); + key.fDatime.setHours((datime << 15) >>> 27); + key.fDatime.setMinutes((datime << 20) >>> 26); + key.fDatime.setSeconds((datime << 26) >>> 26); + key.fDatime.setMilliseconds(0); + key.fKeylen = this.ntou2(); + key.fCycle = this.ntou2(); + if (key.fVersion > 1000) { + key.fSeekKey = this.ntou8(); + this.shift(8); // skip seekPdir + } else { + key.fSeekKey = this.ntou4(); + this.shift(4); // skip seekPdir + } + key.fClassName = this.ReadTString(); + key.fName = this.ReadTString(); + key.fTitle = this.ReadTString(); + + var name = key.fName.replace(/['"]/g,''); + + if (name !== key.fName) { + key.fRealName = key.fName; + key.fName = name; + } + + return true; + } + + JSROOT.TBuffer.prototype.ReadTBasket = function(obj) { + this.ReadTKey(obj); + var ver = this.ReadVersion(); + obj.fBufferSize = this.ntoi4(); + obj.fNevBufSize = this.ntoi4(); + obj.fNevBuf = this.ntoi4(); + obj.fLast = this.ntoi4(); + var flag = this.ntoi1(); + // here we implement only data skipping, no real I/O for TBasket is performed + if ((flag % 10) != 2) { + var sz = this.ntoi4(); this.shift(sz*4); // fEntryOffset + if (flag>40) { sz = this.ntoi4(); this.shift(sz*4); } // fDisplacement + } + + if (flag == 1 || flag > 10) { + var sz = obj.fLast; + if (ver.val <= 1) sz = this.ntoi4(); + this.o += sz; // fBufferRef + } + return this.CheckBytecount(ver,"ReadTBasket"); + } + + JSROOT.TBuffer.prototype.ReadClass = function() { + // read class definition from I/O buffer + var classInfo = { name: -1 }; + var tag = 0; + var bcnt = this.ntou4(); + + var startpos = this.o; + if (!(bcnt & JSROOT.IO.kByteCountMask) || (bcnt == JSROOT.IO.kNewClassTag)) { + tag = bcnt; + bcnt = 0; + } else { + tag = this.ntou4(); + } + if (!(tag & JSROOT.IO.kClassMask)) { + classInfo.objtag = tag; // indicate that we have deal with objects tag + return classInfo; + } + if (tag == JSROOT.IO.kNewClassTag) { + // got a new class description followed by a new object + classInfo.name = this.ReadString(); + + if (this.GetMappedClass(this.fTagOffset + startpos + JSROOT.IO.kMapOffset) === -1) + this.MapClass(this.fTagOffset + startpos + JSROOT.IO.kMapOffset, classInfo.name); + } + else { + // got a tag to an already seen class + var clTag = (tag & ~JSROOT.IO.kClassMask); + classInfo.name = this.GetMappedClass(clTag); + + if (classInfo.name === -1) { + alert("Did not found class with tag " + clTag); + } + + } + + return classInfo; + } + + JSROOT.TBuffer.prototype.ReadObjectAny = function() { + var objtag = this.fTagOffset + this.o + JSROOT.IO.kMapOffset; + + var clRef = this.ReadClass(); + + // class identified as object and should be handled so + if ('objtag' in clRef) + return this.GetMappedObject(clRef.objtag); + + if (clRef.name === -1) return null; + + var arrkind = JSROOT.IO.GetArrayKind(clRef.name); + + var obj = {}; + + if (arrkind > 0) { + // reading array, can map array only afterwards + obj = this.ReadFastArray(this.ntou4(), arrkind); + this.MapObject(objtag, obj); + } else { + // reading normal object, should map before to + this.MapObject(objtag, obj); + this.ClassStreamer(obj, clRef.name); + } + + return obj; + } + + JSROOT.TBuffer.prototype.ClassStreamer = function(obj, classname) { + + if (! ('_typename' in obj)) obj._typename = classname; + + var streamer = this.fFile.GetStreamer(classname); + + if (streamer !== null) { + + var ver = this.ReadVersion(); + + for (var n = 0; n < streamer.length; ++n) + streamer[n].func(this, obj); + + this.CheckBytecount(ver, classname); + // methods will be assigned by last entry in the streamer + + } + else if (classname == 'TQObject') { + // skip TQObject + } + else if (classname == "TBasket") { + this.ReadTBasket(obj); + JSROOT.addMethods(obj); + } else { + // just skip bytes belonging to not-recognized object + // console.warn('skip object ', classname); + + var ver = this.ReadVersion(); + this.CheckBytecount(ver); + JSROOT.addMethods(obj); + } + + + return obj; + } + + // ================================================================================= + + JSROOT.TStrBuffer = function(str, pos, file) { + JSROOT.TBuffer.call(this, pos, file); + this.b = str; + } + + JSROOT.TStrBuffer.prototype = Object.create(JSROOT.TBuffer.prototype); + + JSROOT.TStrBuffer.prototype.totalLength = function() { + return this.b ? this.b.length : 0; + } + + JSROOT.TStrBuffer.prototype.extract = function(off,len) { + return this.b.substr(off, len); + } + + JSROOT.TStrBuffer.prototype.ntou1 = function() { + return (this.b.charCodeAt(this.o++) & 0xff) >>> 0; + } + + JSROOT.TStrBuffer.prototype.ntou2 = function() { + // convert (read) two bytes of buffer b into a UShort_t + var n = ((this.b.charCodeAt(this.o++) & 0xff) << 8) >>> 0; + n += (this.b.charCodeAt(this.o++) & 0xff) >>> 0; + return n; + } + + JSROOT.TStrBuffer.prototype.ntou4 = function() { + // convert (read) four bytes of buffer b into a UInt_t + var n = ((this.b.charCodeAt(this.o++) & 0xff) << 24) >>> 0; + n += ((this.b.charCodeAt(this.o++) & 0xff) << 16) >>> 0; + n += ((this.b.charCodeAt(this.o++) & 0xff) << 8) >>> 0; + n += (this.b.charCodeAt(this.o++) & 0xff) >>> 0; + return n; + } + + JSROOT.TStrBuffer.prototype.ntou8 = function() { + // convert (read) eight bytes of buffer b into a ULong_t + var n = ((this.b.charCodeAt(this.o++) & 0xff) << 56) >>> 0; + n += ((this.b.charCodeAt(this.o++) & 0xff) << 48) >>> 0; + n += ((this.b.charCodeAt(this.o++) & 0xff) << 40) >>> 0; + n += ((this.b.charCodeAt(this.o++) & 0xff) << 32) >>> 0; + n += ((this.b.charCodeAt(this.o++) & 0xff) << 24) >>> 0; + n += ((this.b.charCodeAt(this.o++) & 0xff) << 16) >>> 0; + n += ((this.b.charCodeAt(this.o++) & 0xff) << 8) >>> 0; + n += (this.b.charCodeAt(this.o++) & 0xff) >>> 0; + return n; + } + + JSROOT.TStrBuffer.prototype.ntoi1 = function() { + return (this.b.charCodeAt(this.o++) & 0xff); + } + + JSROOT.TStrBuffer.prototype.ntoi2 = function() { + // convert (read) two bytes of buffer b into a Short_t + var n = ((this.b.charCodeAt(this.o++) & 0xff) << 8); + n += ((this.b.charCodeAt(this.o++) & 0xff)); + return (n < 0x8000) ? n : -1 - (~n &0xFFFF); + } + + JSROOT.TStrBuffer.prototype.ntoi4 = function() { + // convert (read) four bytes of buffer b into a Int_t + var n = ((this.b.charCodeAt(this.o++) & 0xff) << 24); + n += ((this.b.charCodeAt(this.o++) & 0xff) << 16); + n += ((this.b.charCodeAt(this.o++) & 0xff) << 8); + n += ((this.b.charCodeAt(this.o++) & 0xff)); + return n; + } + + JSROOT.TStrBuffer.prototype.ntoi8 = function(b, o) { + // convert (read) eight bytes of buffer b into a Long_t + var n = (this.b.charCodeAt(this.o++) & 0xff) << 56; + n += (this.b.charCodeAt(this.o++) & 0xff) << 48; + n += (this.b.charCodeAt(this.o++) & 0xff) << 40; + n += (this.b.charCodeAt(this.o++) & 0xff) << 32; + n += (this.b.charCodeAt(this.o++) & 0xff) << 24; + n += (this.b.charCodeAt(this.o++) & 0xff) << 16; + n += (this.b.charCodeAt(this.o++) & 0xff) << 8; + n += (this.b.charCodeAt(this.o++) & 0xff); + return n; + } + + JSROOT.TStrBuffer.prototype.ntof = function() { + // IEEE-754 Floating-Point Conversion (single precision - 32 bits) + var inString = this.b.substring(this.o, this.o + 4); this.o+=4; + if (inString.length < 4) return Number.NaN; + var bits = ""; + for (var i=0; i<4; ++i) { + var curByte = (inString.charCodeAt(i) & 0xff).toString(2); + var byteLen = curByte.length; + if (byteLen < 8) { + for (var bit=0; bit<(8-byteLen); ++bit) + curByte = '0' + curByte; + } + bits = bits + curByte; + } + //var bsign = parseInt(bits[0]) ? -1 : 1; + var bsign = (bits.charAt(0) == '1') ? -1 : 1; + var bexp = parseInt(bits.substring(1, 9), 2) - 127; + var bman; + if (bexp == -127) + bman = 0; + else { + bman = 1; + for (var i=0; i<23; ++i) { + if (parseInt(bits.substr(9+i, 1)) == 1) + bman = bman + 1 / Math.pow(2, i+1); + } + } + var res = bsign * Math.pow(2, bexp) * bman; + return (Math.abs(res) < 1e-300) ? 0.0 : res; + } + + JSROOT.TStrBuffer.prototype.ntod = function() { + // IEEE-754 Floating-Point Conversion (double precision - 64 bits) + var inString = this.b.substring(this.o, this.o + 8); this.o+=8; + if (inString.length < 8) return Number.NaN; + var bits = ""; + for (var i=0; i<8; ++i) { + var curByte = (inString.charCodeAt(i) & 0xff).toString(2); + var byteLen = curByte.length; + if (byteLen < 8) { + for (var bit=0; bit<(8-byteLen); ++bit) + curByte = '0' + curByte; + } + bits = bits + curByte; + } + //var bsign = parseInt(bits[0]) ? -1 : 1; + var bsign = (bits.charAt(0) == '1') ? -1 : 1; + var bexp = parseInt(bits.substring(1, 12), 2) - 1023; + var bman; + if (bexp == -127) + bman = 0; + else { + bman = 1; + for (var i=0; i<52; ++i) { + if (parseInt(bits.substr(12+i, 1)) == 1) + bman = bman + 1 / Math.pow(2, i+1); + } + } + var res = (bsign * Math.pow(2, bexp) * bman); + return (Math.abs(res) < 1e-300) ? 0.0 : res; + } + + JSROOT.TStrBuffer.prototype.codeAt = function(pos) { + return this.b.charCodeAt(pos) & 0xff; + } + + JSROOT.TStrBuffer.prototype.substring = function(beg, end) { + return this.b.substring(beg, end); + } + + // ======================================================================= + + JSROOT.TArrBuffer = function(arr, pos, file) { + // buffer should work with DataView as first argument + JSROOT.TBuffer.call(this, pos, file); + this.arr = arr; + } + + JSROOT.TArrBuffer.prototype = Object.create(JSROOT.TBuffer.prototype); + + JSROOT.TArrBuffer.prototype.totalLength = function() { + return this.arr && this.arr.buffer ? this.arr.buffer.byteLength : 0; + } + + JSROOT.TArrBuffer.prototype.extract = function(off,len) { + if (!this.arr || !this.arr.buffer || (this.arr.buffer.byteLength < off+len)) return null; + return new DataView(this.arr.buffer, off, len); + } + + JSROOT.TArrBuffer.prototype.codeAt = function(pos) { + return this.arr.getUint8(pos); + } + + JSROOT.TArrBuffer.prototype.substring = function(beg, end) { + var res = ""; + for (var n=beg;n 0) { + var dirname = keyname.substr(0, pos); + var subname = keyname.substr(pos+1); + + var dirkey = this.GetKey(dirname, 1); + if ((dirkey!==null) && (typeof call_back == 'function') && + (dirkey.fClassName.indexOf("TDirectory")==0)) { + + this.fFile.ReadObject(this.dir_name + "/" + dirname, 1, function(newdir) { + if (newdir) newdir.GetKey(subname, cycle, call_back); + }); + return null; + } + + pos = keyname.lastIndexOf("/", pos-1); + } + + + JSROOT.CallBack(call_back, null); + return null; + } + + JSROOT.TDirectory.prototype.ReadKeys = function(readkeys_callback) { + var thisdir = this; + var file = this.fFile; + + //*-*-------------Read directory info + var nbytes = this.fNbytesName + 22; + nbytes += 4; // fDatimeC.Sizeof(); + nbytes += 4; // fDatimeM.Sizeof(); + nbytes += 18; // fUUID.Sizeof(); + // assume that the file may be above 2 Gbytes if file version is > 4 + if (file.fVersion >= 40000) nbytes += 12; + + file.Seek(this.fSeekDir, this.fFile.ERelativeTo.kBeg); + file.ReadBuffer(nbytes, function(blob1) { + if (blob1==null) return JSROOT.CallBack(readkeys_callback,null); + var buf = JSROOT.CreateTBuffer(blob1, thisdir.fNbytesName, file); + + thisdir.StreamHeader(buf); + + //*-*---------read TKey::FillBuffer info + buf.locate(4); // Skip NBytes; + var keyversion = buf.ntoi2(); + // Skip ObjLen, DateTime, KeyLen, Cycle, SeekKey, SeekPdir + if (keyversion > 1000) buf.shift(28); // Large files + else buf.shift(20); + buf.ReadTString(); + buf.ReadTString(); + thisdir.fTitle = buf.ReadTString(); + if (thisdir.fNbytesName < 10 || thisdir.fNbytesName > 10000) { + JSROOT.console("Cannot read directory info of file " + file.fURL); + return JSROOT.CallBack(readkeys_callback, null); + } + //*-* -------------Read keys of the top directory + + if (thisdir.fSeekKeys <=0) + return JSROOT.CallBack(readkeys_callback, null); + + file.Seek(thisdir.fSeekKeys, file.ERelativeTo.kBeg); + file.ReadBuffer(thisdir.fNbytesKeys, function(blob2) { + if (blob2 == null) return JSROOT.CallBack(readkeys_callback, null); + var buf = JSROOT.CreateTBuffer(blob2, 0, file); + + var key = file.ReadKey(buf); + + var nkeys = buf.ntoi4(); + for (var i = 0; i < nkeys; ++i) { + key = file.ReadKey(buf); + thisdir.fKeys.push(key); + } + file.fDirectories.push(thisdir); + delete buf; + + JSROOT.CallBack(readkeys_callback, thisdir); + }); + + delete buf; + }); + } + + JSROOT.TDirectory.prototype.StreamHeader = function(buf) { + var version = buf.ntou2(); + var versiondir = version % 1000; + buf.shift(8); // skip fDatimeC and fDatimeM + this.fNbytesKeys = buf.ntou4(); + this.fNbytesName = buf.ntou4(); + this.fSeekDir = (version > 1000) ? buf.ntou8() : buf.ntou4(); + this.fSeekParent = (version > 1000) ? buf.ntou8() : buf.ntou4(); + this.fSeekKeys = (version > 1000) ? buf.ntou8() : buf.ntou4(); + if (versiondir > 2) buf.shift(18); // skip fUUID + } + + + // ============================================================================== + // A class that reads ROOT files. + // + //////////////////////////////////////////////////////////////////////////////// + // A ROOT file is a suite of consecutive data records (TKey's) with + // the following format (see also the TKey class). If the key is + // located past the 32 bit file limit (> 2 GB) then some fields will + // be 8 instead of 4 bytes: + // 1->4 Nbytes = Length of compressed object (in bytes) + // 5->6 Version = TKey version identifier + // 7->10 ObjLen = Length of uncompressed object + // 11->14 Datime = Date and time when object was written to file + // 15->16 KeyLen = Length of the key structure (in bytes) + // 17->18 Cycle = Cycle of key + // 19->22 [19->26] SeekKey = Pointer to record itself (consistency check) + // 23->26 [27->34] SeekPdir = Pointer to directory header + // 27->27 [35->35] lname = Number of bytes in the class name + // 28->.. [36->..] ClassName = Object Class Name + // ..->.. lname = Number of bytes in the object name + // ..->.. Name = lName bytes with the name of the object + // ..->.. lTitle = Number of bytes in the object title + // ..->.. Title = Title of the object + // -----> DATA = Data bytes associated to the object + // + + // ctor + JSROOT.TFile = function(url, newfile_callback) { + if (! (this instanceof arguments.callee) ) + throw new Error("you must use new to instantiate this class", "JSROOT.TFile.ctor"); + + this._typename = "TFile"; + this.fOffset = 0; + this.fEND = 0; + this.fFullURL = url; + this.fURL = url; + this.fAcceptRanges = true; // when disabled ('+' at the end of file name), complete file content read with single operation + this.fUseStampPar = new Date; // use additional time stamp parameter for file name to avoid browser caching problem + this.fFileContent = null; // this can be full or parial content of the file (if ranges are not supported or if 1K header read from file) + // stored as TBuffer instance + + this.ERelativeTo = { kBeg : 0, kCur : 1, kEnd : 2 }; + this.fDirectories = new Array(); + this.fKeys = new Array(); + this.fSeekInfo = 0; + this.fNbytesInfo = 0; + this.fTagOffset = 0; + this.fStreamers = 0; + this.fStreamerInfos = null; + this.fFileName = ""; + this.fStreamers = new Array; + + if (typeof this.fURL != 'string') return this; + + if (this.fURL.charAt(this.fURL.length-1) == "+") { + this.fURL = this.fURL.substr(0, this.fURL.length-1); + this.fAcceptRanges = false; + } + + var pos = Math.max(this.fURL.lastIndexOf("/"), this.fURL.lastIndexOf("\\")); + this.fFileName = pos>=0 ? this.fURL.substr(pos+1) : this.fURL; + + if (!this.fAcceptRanges) { + this.ReadKeys(newfile_callback); + } else { + var file = this; + + var xhr = JSROOT.NewHttpRequest(this.fURL, "head", function(res) { + if (res==null) + return JSROOT.CallBack(newfile_callback, null); + + var accept_ranges = res.getResponseHeader("Accept-Ranges"); + if (accept_ranges==null) file.fAcceptRanges = false; + var len = res.getResponseHeader("Content-Length"); + if (len!=null) file.fEND = parseInt(len); + else file.fAcceptRanges = false; + file.ReadKeys(newfile_callback); + }); + + xhr.send(null); + } + + return this; + } + + JSROOT.TFile.prototype.ReadBuffer = function(len, callback) { + + if ((this.fFileContent!=null) && (!this.fAcceptRanges || (this.fOffset+len <= this.fFileContent.totalLength()))) + return callback(this.fFileContent.extract(this.fOffset, len)); + + var file = this; + + var url = this.fURL; + if (this.fUseStampPar) { + // try to avoid browser caching by adding stamp parameter to URL + if (url.indexOf('?')>0) url+="&stamp="; else url += "?stamp="; + url += this.fUseStampPar.getTime(); + } + + function read_callback(res) { + + if ((res==null) && file.fUseStampPar && (file.fOffset==0)) { + // if fail to read file with stamp parameter, try once again without it + file.fUseStampPar = false; + var xhr2 = JSROOT.NewHttpRequest(this.fURL, ((JSROOT.IO.Mode == "array") ? "buf" : "bin"), read_callback); + if (this.fAcceptRanges) + xhr2.setRequestHeader("Range", "bytes=" + this.fOffset + "-" + (this.fOffset + len - 1)); + xhr2.send(null); + return; + } else + if ((res!=null) && (file.fOffset==0) && (file.fFileContent == null)) { + // special case - keep content of first request (could be complete file) in memory + + file.fFileContent = JSROOT.CreateTBuffer((typeof res == 'string') ? res : new DataView(res)); + + if (!this.fAcceptRanges) + file.fEND = file.fFileContent.totalLength(); + + return callback(file.fFileContent.extract(file.fOffset, len)); + } + + if ((res==null) || (res === undefined) || (typeof res == 'string')) + return callback(res); + + // return data view with binary data + callback(new DataView(res)); + } + + var xhr = JSROOT.NewHttpRequest(url, ((JSROOT.IO.Mode == "array") ? "buf" : "bin"), read_callback); + if (this.fAcceptRanges) + xhr.setRequestHeader("Range", "bytes=" + this.fOffset + "-" + (this.fOffset + len - 1)); + xhr.send(null); + } + + JSROOT.TFile.prototype.Seek = function(offset, pos) { + // Set position from where to start reading. + switch (pos) { + case this.ERelativeTo.kBeg: + this.fOffset = offset; + break; + case this.ERelativeTo.kCur: + this.fOffset += offset; + break; + case this.ERelativeTo.kEnd: + // this option is not used currently in the ROOT code + if (this.fEND == 0) + throw new Error("Seek : seeking from end in file with fEND==0 is not supported"); + this.fOffset = this.fEND - offset; + break; + default: + throw new Error("Seek : unknown seek option (" + pos + ")"); + break; + } + } + + JSROOT.TFile.prototype.ReadKey = function(buf) { + // read key from buffer + var key = {}; + buf.ReadTKey(key); + return key; + } + + JSROOT.TFile.prototype.GetDir = function(dirname, cycle) { + // check first that directory with such name exists + + if ((cycle==null) && (typeof dirname == 'string')) { + var pos = dirname.lastIndexOf(';'); + if (pos>0) { cycle = dirname.substr(pos+1); dirname = dirname.substr(0,pos); } + } + + for (var j=0; j < this.fDirectories.length; ++j) { + var dir = this.fDirectories[j]; + if (dir.dir_name != dirname) continue; + if ((cycle !== undefined) && (dir.dir_cycle !== cycle)) continue; + return dir; + } + return null; + } + + JSROOT.TFile.prototype.GetKey = function(keyname, cycle, getkey_callback) { + // retrieve a key by its name and cycle in the list of keys + // one should call_back when keys must be read first from the directory + + for (var i=0; i < this.fKeys.length; ++i) { + if (this.fKeys[i].fName === keyname && this.fKeys[i].fCycle === cycle) { + JSROOT.CallBack(getkey_callback, this.fKeys[i]); + return this.fKeys[i]; + } + } + + var pos = keyname.lastIndexOf("/"); + // try to handle situation when object name contains slashed (bad practice anyway) + while (pos > 0) { + var dirname = keyname.substr(0, pos); + var subname = keyname.substr(pos+1); + + var dir = this.GetDir(dirname); + if (dir!=null) return dir.GetKey(subname, cycle, getkey_callback); + + var dirkey = this.GetKey(dirname, 1); + if ((dirkey !== null) && (getkey_callback != null) && + (dirkey.fClassName.indexOf("TDirectory")==0)) { + + this.ReadObject(dirname, function(newdir) { + if (newdir) newdir.GetKey(subname, cycle, getkey_callback); + }); + return null; + } + + pos = keyname.lastIndexOf("/", pos-1); + } + + JSROOT.CallBack(getkey_callback, null); + return null; + } + + JSROOT.TFile.prototype.ReadObjBuffer = function(key, callback) { + // read and inflate object buffer described by its key + + var file = this; + + this.Seek(key.fSeekKey + key.fKeylen, this.ERelativeTo.kBeg); + + this.ReadBuffer(key.fNbytes - key.fKeylen, function(blob1) { + + if (blob1==null) callback(null); + + var buf = null; + + if (key.fObjlen <= key.fNbytes - key.fKeylen) { + buf = JSROOT.CreateTBuffer(blob1, 0, file); + } else { + var objbuf = JSROOT.R__unzip(blob1, key.fObjlen); + if (objbuf==null) return callback(null); + buf = JSROOT.CreateTBuffer(objbuf, 0, file); + } + + buf.fTagOffset = key.fKeylen; + + callback(buf); + }); + } + + JSROOT.TFile.prototype.ReadObject = function(obj_name, cycle, user_call_back) { + // Read any object from a root file + // One could specify cycle number in the object name or as separate argument + // Last argument should be callback function, while data reading from file is asynchron + + if (typeof cycle == 'function') { user_call_back = cycle; cycle = 1; } + + var pos = obj_name.lastIndexOf(";"); + if (pos>0) { + cycle = parseInt(obj_name.slice(pos+1)); + obj_name = obj_name.slice(0, pos); + } + + if ((typeof cycle != 'number') || (cycle<0)) cycle = 1; + // remove leading slashes + while ((obj_name.length>0) && (obj_name[0] == "/")) obj_name = obj_name.substr(1); + + var file = this; + + // we use callback version while in some cases we need to + // read sub-directory to get list of keys + // in such situation calls are asynchrone + this.GetKey(obj_name, cycle, function(key) { + + if (key == null) + return JSROOT.CallBack(user_call_back, null); + + if ((obj_name=="StreamerInfo") && (key.fClassName=="TList")) + return file.fStreamerInfos; + + var isdir = false; + if ((key.fClassName == 'TDirectory' || key.fClassName == 'TDirectoryFile')) { + isdir = true; + var dir = file.GetDir(obj_name, cycle); + if (dir!=null) + return JSROOT.CallBack(user_call_back, dir); + } + + file.ReadObjBuffer(key, function(buf) { + if (!buf) return JSROOT.CallBack(user_call_back, null); + + if (isdir) { + var dir = new JSROOT.TDirectory(file, obj_name, cycle); + dir.StreamHeader(buf); + if (dir.fSeekKeys) { + dir.ReadKeys(user_call_back); + } else { + JSROOT.CallBack(user_call_back,dir); + } + + return; + } + + var obj = {}; + buf.MapObject(1, obj); // tag object itself with id==1 + buf.ClassStreamer(obj, key.fClassName); + + if (key.fClassName==='TF1') + return file.ReadFormulas(obj, user_call_back, -1); + + JSROOT.CallBack(user_call_back, obj); + }); // end of ReadObjBuffer callback + }); // end of GetKey callback + } + + JSROOT.TFile.prototype.ReadFormulas = function(tf1, user_call_back, cnt) { + + var indx = cnt; + while (++indx < this.fKeys.length) { + if (this.fKeys[indx].fClassName == 'TFormula') break; + } + + if (indx >= this.fKeys.length) + return JSROOT.CallBack(user_call_back, tf1); + + var file = this; + + this.ReadObject(this.fKeys[indx].fName, this.fKeys[indx].fCycle, function(formula) { + tf1.addFormula(formula); + file.ReadFormulas(tf1, user_call_back, indx); + }); + } + + JSROOT.TFile.prototype.ExtractStreamerInfos = function(buf) { + if (!buf) return; + + var lst = {}; + buf.MapObject(1, lst); + buf.ClassStreamer(lst, 'TList'); + + lst._typename = "TStreamerInfoList"; + + this.fStreamerInfos = lst; + + if (typeof JSROOT.addStreamerInfos === 'function') + JSROOT.addStreamerInfos(lst); + } + + + JSROOT.TFile.prototype.ReadStreamerInfos = function(si_callback) { + if (this.fSeekInfo == 0 || this.fNbytesInfo == 0) return si_callback(null); + this.Seek(this.fSeekInfo, this.ERelativeTo.kBeg); + + var file = this; + + file.ReadBuffer(file.fNbytesInfo, function(blob1) { + var buf = JSROOT.CreateTBuffer(blob1, 0, file); + var key = file.ReadKey(buf); + if (key == null) return si_callback(null); + file.fKeys.push(key); + + file.ReadObjBuffer(key, function(blob2) { + if (blob2==null) return si_callback(null); + file.ExtractStreamerInfos(blob2); + si_callback(file); + }); + }); + } + + JSROOT.TFile.prototype.ReadKeys = function(readkeys_callback) { + // read keys only in the root file + + var file = this; + + // with the first readbuffer we read bigger amount to create header cache + this.ReadBuffer(1024, function(blob) { + if (blob==null) return JSROOT.CallBack(readkeys_callback, null); + + var buf = JSROOT.CreateTBuffer(blob, 0, file); + + if (buf.substring(0, 4) !== 'root') { + alert("NOT A ROOT FILE! " + file.fURL); + return JSROOT.CallBack(readkeys_callback, null); + } + buf.shift(4); + + file.fVersion = buf.ntou4(); + file.fBEGIN = buf.ntou4(); + if (file.fVersion < 1000000) { //small file + file.fEND = buf.ntou4(); + file.fSeekFree = buf.ntou4(); + file.fNbytesFree = buf.ntou4(); + var nfree = buf.ntoi4(); + file.fNbytesName = buf.ntou4(); + file.fUnits = buf.ntou1(); + file.fCompress = buf.ntou4(); + file.fSeekInfo = buf.ntou4(); + file.fNbytesInfo = buf.ntou4(); + } else { // new format to support large files + file.fEND = buf.ntou8(); + file.fSeekFree = buf.ntou8(); + file.fNbytesFree = buf.ntou4(); + var nfree = buf.ntou4(); + file.fNbytesName = buf.ntou4(); + file.fUnits = buf.ntou1(); + file.fCompress = buf.ntou4(); + file.fSeekInfo = buf.ntou8(); + file.fNbytesInfo = buf.ntou4(); + } + + // empty file + if (!file.fSeekInfo && !file.fNbytesInfo) + return JSROOT.CallBack(readkeys_callback, null); + + //*-*-------------Read directory info + var nbytes = file.fNbytesName + 22; + nbytes += 4; // fDatimeC.Sizeof(); + nbytes += 4; // fDatimeM.Sizeof(); + nbytes += 18; // fUUID.Sizeof(); + // assume that the file may be above 2 Gbytes if file version is > 4 + if (file.fVersion >= 40000) nbytes += 12; + + file.Seek(file.fBEGIN, file.ERelativeTo.kBeg); + + file.ReadBuffer(Math.max(300, nbytes), function(blob3) { + if (blob3==null) return JSROOT.CallBack(readkeys_callback, null); + + var buf3 = JSROOT.CreateTBuffer(blob3, file.fNbytesName, file); + + // we call TDirectory method while TFile is just derived class + JSROOT.TDirectory.prototype.StreamHeader.call(file, buf3); + + //*-*---------read TKey::FillBuffer info + buf3.o = 4; // Skip NBytes; + var keyversion = buf3.ntoi2(); + // Skip ObjLen, DateTime, KeyLen, Cycle, SeekKey, SeekPdir + if (keyversion > 1000) buf3.shift(28); // Large files + else buf3.shift(20); + buf3.ReadTString(); + buf3.ReadTString(); + file.fTitle = buf3.ReadTString(); + if (file.fNbytesName < 10 || this.fNbytesName > 10000) { + JSROOT.console("Init : cannot read directory info of file " + file.fURL); + return JSROOT.CallBack(readkeys_callback, null); + } + //*-* -------------Read keys of the top directory + + if (file.fSeekKeys <= 0) { + JSROOT.console("Empty keys list - not supported" + file.fURL); + return JSROOT.CallBack(readkeys_callback, null); + } + + file.Seek(file.fSeekKeys, file.ERelativeTo.kBeg); + file.ReadBuffer(file.fNbytesKeys, function(blob4) { + + if (blob4==null) return JSROOT.CallBack(readkeys_callback, null); + + var buf4 = JSROOT.CreateTBuffer(blob4, 0, file); + var key = file.ReadKey(buf4); + var nkeys = buf4.ntoi4(); + for (var i = 0; i < nkeys; ++i) { + key = file.ReadKey(buf4); + file.fKeys.push(key); + } + file.ReadStreamerInfos(readkeys_callback); + delete buf4; + }); + delete buf3; + }); + delete buf; + }); + }; + + JSROOT.TFile.prototype.ReadDirectory = function(dir_name, cycle, readdir_callback) { + // read the directory content from a root file + // do not read directory if it is already exists + + return this.ReadObject(dir_name, cycle, readdir_callback); + }; + + JSROOT.TFile.prototype.AddMethods = function(clname, streamer) { + // create additional entries in the streamer, which sets all methods of the class + + if (streamer === null) return streamer; + + var methods = JSROOT.getMethods(clname); + if (methods !== null) + for (var key in methods) + if ((typeof methods[key] === 'function') || (key.indexOf("_")==0)) + streamer.push({ + name: key, + method: methods[key], + func: function(buf,obj) { obj[this.name] = this.method; } + }); + + return streamer; + } + + JSROOT.TFile.prototype.GetStreamer = function(clname) { + // return the streamer for the class 'clname', from the list of streamers + // or generate it from the streamer infos and add it to the list + + var streamer = this.fStreamers[clname]; + if (streamer !== undefined) return streamer; + + // check element in streamer infos, one can have special cases + var s_i = null; + if (this.fStreamerInfos) + for (var i=0; i < this.fStreamerInfos.arr.length; ++i) + if (this.fStreamerInfos.arr[i].fName == clname) { + s_i = this.fStreamerInfos.arr[i]; break; + } + + if (clname == 'TQObject' || clname == "TBasket") { + // these are special cases, which are handled separately + this.fStreamers[clname] = null; + return null; + } + + this.fStreamers[clname] = streamer = new Array; + + if (clname == 'TObject'|| clname == 'TMethodCall') { + streamer.push({ func: function(buf,obj) { + obj.fUniqueID = buf.ntou4(); + obj.fBits = buf.ntou4(); + } }); + return this.AddMethods(clname, streamer); + } + + if (clname == 'TNamed') { + streamer.push({ func : function(buf,obj) { + buf.ReadVersion(); // ignore TObject version + obj.fUniqueID = buf.ntou4(); + obj.fBits = buf.ntou4(); + obj.fName = buf.ReadTString(); + obj.fTitle = buf.ReadTString(); + } }); + return this.AddMethods(clname, streamer); + } + + if ((clname == 'TList') || (clname == 'THashList')) { + streamer.push({ classname: clname, + func : function(buf, obj) { + // stream all objects in the list from the I/O buffer + obj._typename = this.classname; + obj.name = ""; + obj.arr = new Array; + obj.opt = new Array; + if (buf.last_read_version > 3) { + buf.ClassStreamer(obj, "TObject"); + obj.name = buf.ReadTString(); + var nobjects = buf.ntou4(); + for (var i = 0; i < nobjects; ++i) { + obj.arr.push(buf.ReadObjectAny()); + obj.opt.push(buf.ReadTString()); + } + } + } }); + return this.AddMethods(clname, streamer); + } + + if (clname == 'TClonesArray') { + streamer.push({ func : function(buf, list) { + list._typename = "TClonesArray"; + list.name = ""; + list.arr = new Array(); + var ver = buf.last_read_version; + if (ver > 2) + buf.ClassStreamer(list, "TObject"); + if (ver > 1) + list.name = buf.ReadTString(); + var s = buf.ReadTString(); + var classv = s; + var clv = 0; + var pos = s.indexOf(";"); + if (pos != -1) { + classv = s.slice(0, pos); + s = s.slice(pos+1, s.length-pos-1); + clv = parseInt(s); + } + + var nobjects = buf.ntou4(); + if (nobjects < 0) nobjects = -nobjects; // for backward compatibility + var lowerbound = buf.ntou4(); + + // TO BE DONE - READING OF CLONES ARRAY!!! + + //for (var i = 0; i < nobjects; ++i) { + // var obj = buf.ClassStreamer({}, classv); + // list['arr'].push(obj); + //} + }}); + return this.AddMethods(clname, streamer); + } + + if (clname == 'TCanvas') { + streamer.push({ func : function(buf, obj) { + + obj._typename = "TCanvas"; + + buf.ClassStreamer(obj, "TPad"); + + obj.fDISPLAY = buf.ReadTString(); + obj.fDoubleBuffer = buf.ntoi4(); + obj.fRetained = (buf.ntou1() !== 0); + obj.fXsizeUser = buf.ntoi4(); + obj.fYsizeUser = buf.ntoi4(); + obj.fXsizeReal = buf.ntoi4(); + obj.fYsizeReal = buf.ntoi4(); + obj.fWindowTopX = buf.ntoi4(); + obj.fWindowTopY = buf.ntoi4(); + obj.fWindowWidth = buf.ntoi4(); + obj.fWindowHeight = buf.ntoi4(); + obj.fCw = buf.ntou4(); + obj.fCh = buf.ntou4(); + + obj.fCatt = buf.ClassStreamer({}, "TAttCanvas"); + + buf.ntou1(); // ignore b << TestBit(kMoveOpaque); + buf.ntou1(); // ignore b << TestBit(kResizeOpaque); + obj.fHighLightColor = buf.ntoi2(); + obj.fBatch = (buf.ntou1() !== 0); + buf.ntou1(); // ignore b << TestBit(kShowEventStatus); + buf.ntou1(); // ignore b << TestBit(kAutoExec); + buf.ntou1(); // ignore b << TestBit(kMenuBar); + }}); + return this.AddMethods(clname, streamer); + } + + if (clname == 'TObjArray') { + streamer.push({ func : function(buf, list) { + list._typename = "TObjArray"; + list.name = ""; + list.arr = new Array(); + var ver = buf.last_read_version; + if (ver > 2) + buf.ClassStreamer(list, "TObject"); + if (ver > 1) + list.name = buf.ReadTString(); + var nobjects = buf.ntou4(); + var lowerbound = buf.ntou4(); + for (var i = 0; i < nobjects; ++i) + list.arr.push(buf.ReadObjectAny()); + }}); + return this.AddMethods(clname, streamer); + } + + if (clname == 'TPolyMarker3D') { + streamer.push({ func : function(buf, marker) { + var ver = buf.last_read_version; + + buf.ClassStreamer(marker, "TObject"); + + buf.ClassStreamer(marker, "TAttMarker"); + + marker.fN = buf.ntoi4(); + + marker.fP = buf.ReadFastArray(marker.fN*3, JSROOT.IO.kFloat); + + marker.fOption = buf.ReadTString(); + + if (ver > 1) + marker.fName = buf.ReadTString(); + else + marker.fName = "TPolyMarker3D"; + }}); + return this.AddMethods(clname, streamer); + } + + if ((clname == 'TObjString') && !s_i) { + // special case when TObjString was stored inside streamer infos, + // than streamer cannot be normally generated + streamer.push({ func : function(buf, obj) { + obj._typename = "TObjString"; + buf.ClassStreamer(obj, "TObject"); + obj.fString = buf.ReadTString(); + }}); + return this.AddMethods(clname, streamer); + } + + if (clname == "TStreamerInfo") { + streamer.push({ func : function(buf, streamerinfo) { + // stream an object of class TStreamerInfo from the I/O buffer + if (buf.last_read_version > 1) { + buf.ClassStreamer(streamerinfo, "TNamed"); + + streamerinfo.fCheckSum = buf.ntou4(); + streamerinfo.fClassVersion = buf.ntou4(); + streamerinfo.fElements = buf.ReadObjectAny(); + } + }}); + return this.AddMethods(clname, streamer); + } + + if (clname == "TStreamerElement") { + streamer.push({ func : function(buf, element) { + // stream an object of class TStreamerElement + + var ver = buf.last_read_version; + buf.ClassStreamer(element, "TNamed"); + element.fType = buf.ntou4(); + element.fSize = buf.ntou4(); + element.fArrayLength = buf.ntou4(); + element.fArrayDim = buf.ntou4(); + element.fMaxIndex = buf.ReadFastArray((ver == 1) ? buf.ntou4() : 5, JSROOT.IO.kUInt); + element.fTypeName = buf.ReadTString(); + + if ((element.fType == JSROOT.IO.kUChar) && (element.fTypeName == "Bool_t" || + element.fTypeName == "bool")) + element.fType = JSROOT.IO.kBool; + if (ver > 1) { + } + if (ver <= 2) { + // In TStreamerElement v2, fSize was holding the size of + // the underlying data type. In later version it contains + // the full length of the data member. + } + if (ver == 3) { + element.fXmin = buf.ntod(); + element.fXmax = buf.ntod(); + element.fFactor = buf.ntod(); + } + if (ver > 3) { + } + }}); + return this.AddMethods(clname, streamer); + } + + if (clname == "TStreamerBase") { + streamer.push({ func : function(buf, elem) { + // stream an object of class TStreamerBase + + var ver = buf.last_read_version; + buf.ClassStreamer(elem, "TStreamerElement"); + if (ver > 2) { + elem.fBaseVersion = buf.ntou4(); + } + }}); + return this.AddMethods(clname, streamer); + } + + if ((clname == "TStreamerBasicPointer") || (clname == "TStreamerLoop")) { + streamer.push({ func : function(buf,elem) { + // stream an object of class TStreamerBasicPointer + if (buf.last_read_version > 1) { + buf.ClassStreamer(elem, "TStreamerElement"); + elem.fCountVersion = buf.ntou4(); + elem.fCountName = buf.ReadTString(); + elem.fCountClass = buf.ReadTString(); + } + }}); + return this.AddMethods(clname, streamer); + } + + if (clname == "TStreamerSTL") { + streamer.push({ func : function(buf, elem) { + if (buf.last_read_version > 1) { + buf.ClassStreamer(elem, "TStreamerElement"); + elem.fSTLtype = buf.ntou4(); + elem.fCtype = buf.ntou4(); + } + }}); + return streamer; + } + + if (clname == "TStreamerObject" || clname == "TStreamerBasicType" || + clname == "TStreamerObjectAny" || clname == "TStreamerString" || + clname == "TStreamerObjectPointer") { + streamer.push({ func: function(buf, elem) { + if (buf.last_read_version > 1) + buf.ClassStreamer(elem, "TStreamerElement"); + }}); + return this.AddMethods(clname, streamer); + } + + if (clname == "TStreamerObjectAnyPointer") { + streamer.push({ func: function(buf, elem) { + if (buf.last_read_version > 0) + buf.ClassStreamer(elem, "TStreamerElement"); + }}); + return this.AddMethods(clname, streamer); + } + + if (s_i == null) { + delete this.fStreamers[clname]; + // console.warn('did not find streamer for ', clname); + return null; + } + + if (s_i.fElements === null) + return this.AddMethods(clname, streamer); + + + for (var j=0; j 0) { + // this is workaround for arrays as base class + // we create 'fArray' member, which read as any other data member + member.name = 'fArray'; + member.type = JSROOT.IO.kAny; + } else { + // create streamer for base class + member.type = JSROOT.IO.kBase; + this.GetStreamer(element.fName); + } + } + + switch (member.type) { + case JSROOT.IO.kBase: + member.func = function(buf, obj) { + buf.ClassStreamer(obj, this.name); + }; + break; + case JSROOT.IO.kTString: + member.func = function(buf,obj) { obj[this.name] = buf.ReadTString(); }; break; + case JSROOT.IO.kAnyP: + case JSROOT.IO.kObjectP: + member.func = function(buf,obj) { obj[this.name] = buf.ReadObjectAny(); }; break; + case JSROOT.IO.kOffsetL+JSROOT.IO.kBool: + case JSROOT.IO.kOffsetL+JSROOT.IO.kInt: + case JSROOT.IO.kOffsetL+JSROOT.IO.kDouble: + case JSROOT.IO.kOffsetL+JSROOT.IO.kShort: + case JSROOT.IO.kOffsetL+JSROOT.IO.kUShort: + case JSROOT.IO.kOffsetL+JSROOT.IO.kUInt: + case JSROOT.IO.kOffsetL+JSROOT.IO.kULong: + case JSROOT.IO.kOffsetL+JSROOT.IO.kULong64: + case JSROOT.IO.kOffsetL+JSROOT.IO.kLong: + case JSROOT.IO.kOffsetL+JSROOT.IO.kLong64: + case JSROOT.IO.kOffsetL+JSROOT.IO.kFloat: + case JSROOT.IO.kOffsetL+JSROOT.IO.kDouble32: + if (element.fArrayDim === 1) { + member.arrlength = element.fArrayLength; + member.func = function(buf, obj) { + obj[this.name] = buf.ReadFastArray(this.arrlength, this.type - JSROOT.IO.kOffsetL); + }; + } else + if (element.fArrayDim === 2) { + member.arrlength = element.fMaxIndex[1]; + member.maxindx = element.fMaxIndex[0]; + member.func = function(buf, obj) { + obj[this.name] = []; + for (var n=0;n0)) { + indx[k] = 0; + arr[k-1].push(arr[k]); + arr[k] = []; + ++indx[--k]; + } + } + obj[this.name] = arr[0]; + }; + } + break; + case JSROOT.IO.kOffsetP+JSROOT.IO.kBool: + case JSROOT.IO.kOffsetP+JSROOT.IO.kInt: + case JSROOT.IO.kOffsetP+JSROOT.IO.kDouble: + case JSROOT.IO.kOffsetP+JSROOT.IO.kUChar: + case JSROOT.IO.kOffsetP+JSROOT.IO.kChar: + case JSROOT.IO.kOffsetP+JSROOT.IO.kShort: + case JSROOT.IO.kOffsetP+JSROOT.IO.kUShort: + case JSROOT.IO.kOffsetP+JSROOT.IO.kUInt: + case JSROOT.IO.kOffsetP+JSROOT.IO.kULong: + case JSROOT.IO.kOffsetP+JSROOT.IO.kULong64: + case JSROOT.IO.kOffsetP+JSROOT.IO.kLong: + case JSROOT.IO.kOffsetP+JSROOT.IO.kLong64: + case JSROOT.IO.kOffsetP+JSROOT.IO.kFloat: + case JSROOT.IO.kOffsetP+JSROOT.IO.kDouble32: + member.cntname = element.fCountName; + member.func = function(buf, obj) { + if (buf.ntou1() === 1) + obj[this.name] = buf.ReadFastArray(obj[this.cntname], this.type - JSROOT.IO.kOffsetP); + else + obj[this.name] = new Array(); + }; + break; + case JSROOT.IO.kAny: + case JSROOT.IO.kAnyp: + case JSROOT.IO.kObjectp: + case JSROOT.IO.kObject: + var classname = (element.fTypeName === 'BASE') ? element.fName : element.fTypeName; + if (classname.charAt(classname.length-1) == "*") + classname = classname.substr(0, classname.length - 1); + + var arrkind = JSROOT.IO.GetArrayKind(classname); + + if (arrkind > 0) { + member.arrkind = arrkind; + member.func = function(buf, obj) { + obj[this.name] = buf.ReadFastArray(buf.ntou4(), this.arrkind); + }; + } else + if (arrkind === 0) { + member.func = function(buf,obj) { obj[this.name] = buf.ReadTString(); }; + } else { + member.classname = classname; + member.func = function(buf, obj) { + obj[this.name] = buf.ClassStreamer({}, this.classname); + }; + } + break; + case JSROOT.IO.kOffsetL + JSROOT.IO.kObject: + case JSROOT.IO.kOffsetL + JSROOT.IO.kAny: + case JSROOT.IO.kOffsetL + JSROOT.IO.kAnyp: + case JSROOT.IO.kOffsetL + JSROOT.IO.kObjectp: + member.arrlength = element.fArrayLength; + var classname = element.fTypeName; + if (classname.charAt(classname.length-1) == "*") + classname = classname.substr(0, classname.length - 1); + + var arrkind = JSROOT.IO.GetArrayKind(classname); + + if (arrkind > 0) { + member.arrkind = arrkind; + member.func = function(buf, obj) { + obj[this.name] = []; + for (var k=0;k") res = buf.ReadFastArray(buf.ntoi4(),JSROOT.IO.kDouble); else + if (this.typename == "vector") res = buf.ReadFastArray(buf.ntoi4(),JSROOT.IO.kInt); else + if (this.typename == "vector") res = buf.ReadFastArray(buf.ntoi4(),JSROOT.IO.kFloat); else + if (this.typename == "vector") { + var n = buf.ntoi4(); + res = []; + for (var i=0;i=n){if(!e){alert("Error R__unzip: header size exceeds buffer size")}return null}if(!((b(o)=="Z"&&b(o+1)=="L"&&c(o+2)==a.IO.Z_DEFLATED))){if(!e){alert("R__unzip: Old zlib format is not supported!")}return null}var m=a.IO.Z_HDRSIZE+((c(o+3)&255)|((c(o+4)&255)<<8)|((c(o+5)&255)<<16));if(f){var g=new Uint8Array(k.buffer,k.byteOffset+o+a.IO.Z_HDRSIZE+2,k.byteLength-o-a.IO.Z_HDRSIZE-2);if(j===null){j=new ArrayBuffer(i)}var l=window.RawInflate.arr_inflate(g,new Uint8Array(j,d));if(l<=0){break}d+=l}else{var h=window.RawInflate.inflate(k.substr(a.IO.Z_HDRSIZE+2+o,m));if((h===null)||(h.length===0)){break}if(j===null){j=h}else{j+=h}d+=h.length}o+=m}if(d!==i){if(!e){alert("R__unzip: fail to unzip data expacts "+i+" , got "+d)}return null}return f?new DataView(j):j};a.TBuffer=function(b,c){this._typename="TBuffer";this.o=(b==null)?0:b;this.fFile=c;this.ClearObjectMap();this.fTagOffset=0;this.last_read_version=0;return this};a.TBuffer.prototype.locate=function(b){this.o=b};a.TBuffer.prototype.shift=function(b){this.o+=b};a.TBuffer.prototype.GetMappedObject=function(b){return this.fObjectMap[b]};a.TBuffer.prototype.MapObject=function(b,c){if(c!==null){this.fObjectMap[b]=c}};a.TBuffer.prototype.MapClass=function(b,c){this.fClassMap[b]=c};a.TBuffer.prototype.GetMappedClass=function(b){if(b in this.fClassMap){return this.fClassMap[b]}return -1};a.TBuffer.prototype.ClearObjectMap=function(){this.fObjectMap={};this.fClassMap={};this.fObjectMap[0]=null};a.TBuffer.prototype.ReadVersion=function(){var b={};var c=this.ntou4();if(c&a.IO.kByteCountMask){b.bytecnt=c-a.IO.kByteCountMask-2}else{this.o-=4}this.last_read_version=b.val=this.ntou2();b.off=this.o;return b};a.TBuffer.prototype.CheckBytecount=function(b,c){if(("bytecnt" in b)&&(b.off+b.bytecnt!==this.o)){if(c!=null){alert("Missmatch in "+c+" bytecount expected = "+b.bytecnt+" got = "+(this.o-b.off))}this.o=b.off+b.bytecnt;return false}return true};a.TBuffer.prototype.ReadString=function(){var c=this.o,b=this.totalLength();while(this.oc)?this.substring(c,this.o-1):""};a.TBuffer.prototype.ReadTString=function(){var b=this.ntou1();if(b==255){b=this.ntou4()}if(b==0){return""}var c=this.o;this.o+=b;return(this.codeAt(c)==0)?"":this.substring(c,c+b)};a.TBuffer.prototype.ReadFastArray=function(e,c){var d=null;switch(c){case a.IO.kDouble:d=a.IO.NativeArray?new Float64Array(e):new Array(e);for(var b=0;b>>26)+1995);c.fDatime.setMonth((d<<6)>>>28);c.fDatime.setDate((d<<10)>>>27);c.fDatime.setHours((d<<15)>>>27);c.fDatime.setMinutes((d<<20)>>>26);c.fDatime.setSeconds((d<<26)>>>26);c.fDatime.setMilliseconds(0);c.fKeylen=this.ntou2();c.fCycle=this.ntou2();if(c.fVersion>1000){c.fSeekKey=this.ntou8();this.shift(8)}else{c.fSeekKey=this.ntou4();this.shift(4)}c.fClassName=this.ReadTString();c.fName=this.ReadTString();c.fTitle=this.ReadTString();var b=c.fName.replace(/['"]/g,"");if(b!==c.fName){c.fRealName=c.fName;c.fName=b}return true};a.TBuffer.prototype.ReadTBasket=function(e){this.ReadTKey(e);var b=this.ReadVersion();e.fBufferSize=this.ntoi4();e.fNevBufSize=this.ntoi4();e.fNevBuf=this.ntoi4();e.fLast=this.ntoi4();var c=this.ntoi1();if((c%10)!=2){var d=this.ntoi4();this.shift(d*4);if(c>40){d=this.ntoi4();this.shift(d*4)}}if(c==1||c>10){var d=e.fLast;if(b.val<=1){d=this.ntoi4()}this.o+=d}return this.CheckBytecount(b,"ReadTBasket")};a.TBuffer.prototype.ReadClass=function(){var f={name:-1};var b=0;var e=this.ntou4();var d=this.o;if(!(e&a.IO.kByteCountMask)||(e==a.IO.kNewClassTag)){b=e;e=0}else{b=this.ntou4()}if(!(b&a.IO.kClassMask)){f.objtag=b;return f}if(b==a.IO.kNewClassTag){f.name=this.ReadString();if(this.GetMappedClass(this.fTagOffset+d+a.IO.kMapOffset)===-1){this.MapClass(this.fTagOffset+d+a.IO.kMapOffset,f.name)}}else{var c=(b&~a.IO.kClassMask);f.name=this.GetMappedClass(c);if(f.name===-1){alert("Did not found class with tag "+c)}}return f};a.TBuffer.prototype.ReadObjectAny=function(){var c=this.fTagOffset+this.o+a.IO.kMapOffset;var e=this.ReadClass();if("objtag" in e){return this.GetMappedObject(e.objtag)}if(e.name===-1){return null}var b=a.IO.GetArrayKind(e.name);var d={};if(b>0){d=this.ReadFastArray(this.ntou4(),b);this.MapObject(c,d)}else{this.MapObject(c,d);this.ClassStreamer(d,e.name)}return d};a.TBuffer.prototype.ClassStreamer=function(e,d){if(!("_typename" in e)){e._typename=d}var c=this.fFile.GetStreamer(d);if(c!==null){var b=this.ReadVersion();for(var f=0;f>>0};a.TStrBuffer.prototype.ntou2=function(){var b=((this.b.charCodeAt(this.o++)&255)<<8)>>>0;b+=(this.b.charCodeAt(this.o++)&255)>>>0;return b};a.TStrBuffer.prototype.ntou4=function(){var b=((this.b.charCodeAt(this.o++)&255)<<24)>>>0;b+=((this.b.charCodeAt(this.o++)&255)<<16)>>>0;b+=((this.b.charCodeAt(this.o++)&255)<<8)>>>0;b+=(this.b.charCodeAt(this.o++)&255)>>>0;return b};a.TStrBuffer.prototype.ntou8=function(){var b=((this.b.charCodeAt(this.o++)&255)<<56)>>>0;b+=((this.b.charCodeAt(this.o++)&255)<<48)>>>0;b+=((this.b.charCodeAt(this.o++)&255)<<40)>>>0;b+=((this.b.charCodeAt(this.o++)&255)<<32)>>>0;b+=((this.b.charCodeAt(this.o++)&255)<<24)>>>0;b+=((this.b.charCodeAt(this.o++)&255)<<16)>>>0;b+=((this.b.charCodeAt(this.o++)&255)<<8)>>>0;b+=(this.b.charCodeAt(this.o++)&255)>>>0;return b};a.TStrBuffer.prototype.ntoi1=function(){return(this.b.charCodeAt(this.o++)&255)};a.TStrBuffer.prototype.ntoi2=function(){var b=((this.b.charCodeAt(this.o++)&255)<<8);b+=((this.b.charCodeAt(this.o++)&255));return(b<32768)?b:-1-(~b&65535)};a.TStrBuffer.prototype.ntoi4=function(){var b=((this.b.charCodeAt(this.o++)&255)<<24);b+=((this.b.charCodeAt(this.o++)&255)<<16);b+=((this.b.charCodeAt(this.o++)&255)<<8);b+=((this.b.charCodeAt(this.o++)&255));return b};a.TStrBuffer.prototype.ntoi8=function(c,d){var e=(this.b.charCodeAt(this.o++)&255)<<56;e+=(this.b.charCodeAt(this.o++)&255)<<48;e+=(this.b.charCodeAt(this.o++)&255)<<40;e+=(this.b.charCodeAt(this.o++)&255)<<32;e+=(this.b.charCodeAt(this.o++)&255)<<24;e+=(this.b.charCodeAt(this.o++)&255)<<16;e+=(this.b.charCodeAt(this.o++)&255)<<8;e+=(this.b.charCodeAt(this.o++)&255);return e};a.TStrBuffer.prototype.ntof=function(){var c=this.b.substring(this.o,this.o+4);this.o+=4;if(c.length<4){return Number.NaN}var l="";for(var d=0;d<4;++d){var b=(c.charCodeAt(d)&255).toString(2);var e=b.length;if(e<8){for(var j=0;j<(8-e);++j){b="0"+b}}l=l+b}var h=(l.charAt(0)=="1")?-1:1;var k=parseInt(l.substring(1,9),2)-127;var f;if(k==-127){f=0}else{f=1;for(var d=0;d<23;++d){if(parseInt(l.substr(9+d,1))==1){f=f+1/Math.pow(2,d+1)}}}var g=h*Math.pow(2,k)*f;return(Math.abs(g)<1e-300)?0:g};a.TStrBuffer.prototype.ntod=function(){var c=this.b.substring(this.o,this.o+8);this.o+=8;if(c.length<8){return Number.NaN}var l="";for(var d=0;d<8;++d){var b=(c.charCodeAt(d)&255).toString(2);var e=b.length;if(e<8){for(var j=0;j<(8-e);++j){b="0"+b}}l=l+b}var h=(l.charAt(0)=="1")?-1:1;var k=parseInt(l.substring(1,12),2)-1023;var f;if(k==-127){f=0}else{f=1;for(var d=0;d<52;++d){if(parseInt(l.substr(12+d,1))==1){f=f+1/Math.pow(2,d+1)}}}var g=(h*Math.pow(2,k)*f);return(Math.abs(g)<1e-300)?0:g};a.TStrBuffer.prototype.codeAt=function(b){return this.b.charCodeAt(b)&255};a.TStrBuffer.prototype.substring=function(c,b){return this.b.substring(c,b)};a.TArrBuffer=function(b,d,c){a.TBuffer.call(this,d,c);this.arr=b};a.TArrBuffer.prototype=Object.create(a.TBuffer.prototype);a.TArrBuffer.prototype.totalLength=function(){return this.arr&&this.arr.buffer?this.arr.buffer.byteLength:0};a.TArrBuffer.prototype.extract=function(c,b){if(!this.arr||!this.arr.buffer||(this.arr.buffer.byteLength0){var f=g.substr(0,j);var h=g.substr(j+1);var d=this.GetKey(f,1);if((d!==null)&&(typeof e=="function")&&(d.fClassName.indexOf("TDirectory")==0)){this.fFile.ReadObject(this.dir_name+"/"+f,1,function(i){if(i){i.GetKey(h,c,e)}});return null}j=g.lastIndexOf("/",j-1)}a.CallBack(e,null);return null};a.TDirectory.prototype.ReadKeys=function(b){var e=this;var d=this.fFile;var c=this.fNbytesName+22;c+=4;c+=4;c+=18;if(d.fVersion>=40000){c+=12}d.Seek(this.fSeekDir,this.fFile.ERelativeTo.kBeg);d.ReadBuffer(c,function(h){if(h==null){return a.CallBack(b,null)}var f=a.CreateTBuffer(h,e.fNbytesName,d);e.StreamHeader(f);f.locate(4);var g=f.ntoi2();if(g>1000){f.shift(28)}else{f.shift(20)}f.ReadTString();f.ReadTString();e.fTitle=f.ReadTString();if(e.fNbytesName<10||e.fNbytesName>10000){a.console("Cannot read directory info of file "+d.fURL);return a.CallBack(b,null)}if(e.fSeekKeys<=0){return a.CallBack(b,null)}d.Seek(e.fSeekKeys,d.ERelativeTo.kBeg);d.ReadBuffer(e.fNbytesKeys,function(n){if(n==null){return a.CallBack(b,null)}var j=a.CreateTBuffer(n,0,d);var l=d.ReadKey(j);var m=j.ntoi4();for(var k=0;k1000)?c.ntou8():c.ntou4();this.fSeekParent=(b>1000)?c.ntou8():c.ntou4();this.fSeekKeys=(b>1000)?c.ntou8():c.ntou4();if(d>2){c.shift(18)}};a.TFile=function(c,b){if(!(this instanceof arguments.callee)){throw new Error("you must use new to instantiate this class","JSROOT.TFile.ctor")}this._typename="TFile";this.fOffset=0;this.fEND=0;this.fFullURL=c;this.fURL=c;this.fAcceptRanges=true;this.fUseStampPar=new Date;this.fFileContent=null;this.ERelativeTo={kBeg:0,kCur:1,kEnd:2};this.fDirectories=new Array();this.fKeys=new Array();this.fSeekInfo=0;this.fNbytesInfo=0;this.fTagOffset=0;this.fStreamers=0;this.fStreamerInfos=null;this.fFileName="";this.fStreamers=new Array;if(typeof this.fURL!="string"){return this}if(this.fURL.charAt(this.fURL.length-1)=="+"){this.fURL=this.fURL.substr(0,this.fURL.length-1);this.fAcceptRanges=false}var f=Math.max(this.fURL.lastIndexOf("/"),this.fURL.lastIndexOf("\\"));this.fFileName=f>=0?this.fURL.substr(f+1):this.fURL;if(!this.fAcceptRanges){this.ReadKeys(b)}else{var d=this;var e=a.NewHttpRequest(this.fURL,"head",function(h){if(h==null){return a.CallBack(b,null)}var i=h.getResponseHeader("Accept-Ranges");if(i==null){d.fAcceptRanges=false}var g=h.getResponseHeader("Content-Length");if(g!=null){d.fEND=parseInt(g)}else{d.fAcceptRanges=false}d.ReadKeys(b)});e.send(null)}return this};a.TFile.prototype.ReadBuffer=function(b,g){if((this.fFileContent!=null)&&(!this.fAcceptRanges||(this.fOffset+b<=this.fFileContent.totalLength()))){return g(this.fFileContent.extract(this.fOffset,b))}var d=this;var c=this.fURL;if(this.fUseStampPar){if(c.indexOf("?")>0){c+="&stamp="}else{c+="?stamp="}c+=this.fUseStampPar.getTime()}function e(h){if((h==null)&&d.fUseStampPar&&(d.fOffset==0)){d.fUseStampPar=false;var i=a.NewHttpRequest(this.fURL,((a.IO.Mode=="array")?"buf":"bin"),e);if(this.fAcceptRanges){i.setRequestHeader("Range","bytes="+this.fOffset+"-"+(this.fOffset+b-1))}i.send(null);return}else{if((h!=null)&&(d.fOffset==0)&&(d.fFileContent==null)){d.fFileContent=a.CreateTBuffer((typeof h=="string")?h:new DataView(h));if(!this.fAcceptRanges){d.fEND=d.fFileContent.totalLength()}return g(d.fFileContent.extract(d.fOffset,b))}}if((h==null)||(h===undefined)||(typeof h=="string")){return g(h)}g(new DataView(h))}var f=a.NewHttpRequest(c,((a.IO.Mode=="array")?"buf":"bin"),e);if(this.fAcceptRanges){f.setRequestHeader("Range","bytes="+this.fOffset+"-"+(this.fOffset+b-1))}f.send(null)};a.TFile.prototype.Seek=function(b,c){switch(c){case this.ERelativeTo.kBeg:this.fOffset=b;break;case this.ERelativeTo.kCur:this.fOffset+=b;break;case this.ERelativeTo.kEnd:if(this.fEND==0){throw new Error("Seek : seeking from end in file with fEND==0 is not supported")}this.fOffset=this.fEND-b;break;default:throw new Error("Seek : unknown seek option ("+c+")");break}};a.TFile.prototype.ReadKey=function(b){var c={};b.ReadTKey(c);return c};a.TFile.prototype.GetDir=function(e,d){if((d==null)&&(typeof e=="string")){var f=e.lastIndexOf(";");if(f>0){d=e.substr(f+1);e=e.substr(0,f)}}for(var c=0;c0){var g=f.substr(0,j);var k=f.substr(j+1);var c=this.GetDir(g);if(c!=null){return c.GetKey(k,d,b)}var h=this.GetKey(g,1);if((h!==null)&&(b!=null)&&(h.fClassName.indexOf("TDirectory")==0)){this.ReadObject(g,function(i){if(i){i.GetKey(k,d,b)}});return null}j=f.lastIndexOf("/",j-1)}a.CallBack(b,null);return null};a.TFile.prototype.ReadObjBuffer=function(c,d){var b=this;this.Seek(c.fSeekKey+c.fKeylen,this.ERelativeTo.kBeg);this.ReadBuffer(c.fNbytes-c.fKeylen,function(g){if(g==null){d(null)}var e=null;if(c.fObjlen<=c.fNbytes-c.fKeylen){e=a.CreateTBuffer(g,0,b)}else{var f=a.R__unzip(g,c.fObjlen);if(f==null){return d(null)}e=a.CreateTBuffer(f,0,b)}e.fTagOffset=c.fKeylen;d(e)})};a.TFile.prototype.ReadObject=function(b,e,d){if(typeof e=="function"){d=e;e=1}var f=b.lastIndexOf(";");if(f>0){e=parseInt(b.slice(f+1));b=b.slice(0,f)}if((typeof e!="number")||(e<0)){e=1}while((b.length>0)&&(b[0]=="/")){b=b.substr(1)}var c=this;this.GetKey(b,e,function(i){if(i==null){return a.CallBack(d,null)}if((b=="StreamerInfo")&&(i.fClassName=="TList")){return c.fStreamerInfos}var g=false;if((i.fClassName=="TDirectory"||i.fClassName=="TDirectoryFile")){g=true;var h=c.GetDir(b,e);if(h!=null){return a.CallBack(d,h)}}c.ReadObjBuffer(i,function(k){if(!k){return a.CallBack(d,null)}if(g){var j=new a.TDirectory(c,b,e);j.StreamHeader(k);if(j.fSeekKeys){j.ReadKeys(d)}else{a.CallBack(d,j)}return}var l={};k.MapObject(1,l);k.ClassStreamer(l,i.fClassName);if(i.fClassName==="TF1"){return c.ReadFormulas(l,d,-1)}a.CallBack(d,l)})})};a.TFile.prototype.ReadFormulas=function(f,d,c){var e=c;while(++e=this.fKeys.length){return a.CallBack(d,f)}var b=this;this.ReadObject(this.fKeys[e].fName,this.fKeys[e].fCycle,function(g){f.addFormula(g);b.ReadFormulas(f,d,e)})};a.TFile.prototype.ExtractStreamerInfos=function(c){if(!c){return}var b={};c.MapObject(1,b);c.ClassStreamer(b,"TList");b._typename="TStreamerInfoList";this.fStreamerInfos=b;if(typeof a.addStreamerInfos==="function"){a.addStreamerInfos(b)}};a.TFile.prototype.ReadStreamerInfos=function(c){if(this.fSeekInfo==0||this.fNbytesInfo==0){return c(null)}this.Seek(this.fSeekInfo,this.ERelativeTo.kBeg);var b=this;b.ReadBuffer(b.fNbytesInfo,function(f){var d=a.CreateTBuffer(f,0,b);var e=b.ReadKey(d);if(e==null){return c(null)}b.fKeys.push(e);b.ReadObjBuffer(e,function(g){if(g==null){return c(null)}b.ExtractStreamerInfos(g);c(b)})})};a.TFile.prototype.ReadKeys=function(b){var c=this;this.ReadBuffer(1024,function(d){if(d==null){return a.CallBack(b,null)}var f=a.CreateTBuffer(d,0,c);if(f.substring(0,4)!=="root"){alert("NOT A ROOT FILE! "+c.fURL);return a.CallBack(b,null)}f.shift(4);c.fVersion=f.ntou4();c.fBEGIN=f.ntou4();if(c.fVersion<1000000){c.fEND=f.ntou4();c.fSeekFree=f.ntou4();c.fNbytesFree=f.ntou4();var g=f.ntoi4();c.fNbytesName=f.ntou4();c.fUnits=f.ntou1();c.fCompress=f.ntou4();c.fSeekInfo=f.ntou4();c.fNbytesInfo=f.ntou4()}else{c.fEND=f.ntou8();c.fSeekFree=f.ntou8();c.fNbytesFree=f.ntou4();var g=f.ntou4();c.fNbytesName=f.ntou4();c.fUnits=f.ntou1();c.fCompress=f.ntou4();c.fSeekInfo=f.ntou8();c.fNbytesInfo=f.ntou4()}if(!c.fSeekInfo&&!c.fNbytesInfo){return a.CallBack(b,null)}var e=c.fNbytesName+22;e+=4;e+=4;e+=18;if(c.fVersion>=40000){e+=12}c.Seek(c.fBEGIN,c.ERelativeTo.kBeg);c.ReadBuffer(Math.max(300,e),function(j){if(j==null){return a.CallBack(b,null)}var i=a.CreateTBuffer(j,c.fNbytesName,c);a.TDirectory.prototype.StreamHeader.call(c,i);i.o=4;var h=i.ntoi2();if(h>1000){i.shift(28)}else{i.shift(20)}i.ReadTString();i.ReadTString();c.fTitle=i.ReadTString();if(c.fNbytesName<10||this.fNbytesName>10000){a.console("Init : cannot read directory info of file "+c.fURL);return a.CallBack(b,null)}if(c.fSeekKeys<=0){a.console("Empty keys list - not supported"+c.fURL);return a.CallBack(b,null)}c.Seek(c.fSeekKeys,c.ERelativeTo.kBeg);c.ReadBuffer(c.fNbytesKeys,function(o){if(o==null){return a.CallBack(b,null)}var m=a.CreateTBuffer(o,0,c);var l=c.ReadKey(m);var n=m.ntoi4();for(var k=0;k3){j.ClassStreamer(n,"TObject");n.name=j.ReadTString();var o=j.ntou4();for(var m=0;m2){m.ClassStreamer(p,"TObject")}if(o>1){p.name=m.ReadTString()}var t=m.ReadTString();var n=t;var r=0;var q=t.indexOf(";");if(q!=-1){n=t.slice(0,q);t=t.slice(q+1,t.length-q-1);r=parseInt(t)}var j=m.ntou4();if(j<0){j=-j}var i=m.ntou4()}});return this.AddMethods(b,k)}if(b=="TCanvas"){k.push({func:function(i,j){j._typename="TCanvas";i.ClassStreamer(j,"TPad");j.fDISPLAY=i.ReadTString();j.fDoubleBuffer=i.ntoi4();j.fRetained=(i.ntou1()!==0);j.fXsizeUser=i.ntoi4();j.fYsizeUser=i.ntoi4();j.fXsizeReal=i.ntoi4();j.fYsizeReal=i.ntoi4();j.fWindowTopX=i.ntoi4();j.fWindowTopY=i.ntoi4();j.fWindowWidth=i.ntoi4();j.fWindowHeight=i.ntoi4();j.fCw=i.ntou4();j.fCh=i.ntou4();j.fCatt=i.ClassStreamer({},"TAttCanvas");i.ntou1();i.ntou1();j.fHighLightColor=i.ntoi2();j.fBatch=(i.ntou1()!==0);i.ntou1();i.ntou1();i.ntou1()}});return this.AddMethods(b,k)}if(b=="TObjArray"){k.push({func:function(n,p){p._typename="TObjArray";p.name="";p.arr=new Array();var j=n.last_read_version;if(j>2){n.ClassStreamer(p,"TObject")}if(j>1){p.name=n.ReadTString()}var q=n.ntou4();var m=n.ntou4();for(var o=0;o1){j.fName=m.ReadTString()}else{j.fName="TPolyMarker3D"}}});return this.AddMethods(b,k)}if((b=="TObjString")&&!d){k.push({func:function(i,j){j._typename="TObjString";i.ClassStreamer(j,"TObject");j.fString=i.ReadTString()}});return this.AddMethods(b,k)}if(b=="TStreamerInfo"){k.push({func:function(i,j){if(i.last_read_version>1){i.ClassStreamer(j,"TNamed");j.fCheckSum=i.ntou4();j.fClassVersion=i.ntou4();j.fElements=i.ReadObjectAny()}}});return this.AddMethods(b,k)}if(b=="TStreamerElement"){k.push({func:function(j,m){var i=j.last_read_version;j.ClassStreamer(m,"TNamed");m.fType=j.ntou4();m.fSize=j.ntou4();m.fArrayLength=j.ntou4();m.fArrayDim=j.ntou4();m.fMaxIndex=j.ReadFastArray((i==1)?j.ntou4():5,a.IO.kUInt);m.fTypeName=j.ReadTString();if((m.fType==a.IO.kUChar)&&(m.fTypeName=="Bool_t"||m.fTypeName=="bool")){m.fType=a.IO.kBool}if(i>1){}if(i<=2){}if(i==3){m.fXmin=j.ntod();m.fXmax=j.ntod();m.fFactor=j.ntod()}if(i>3){}}});return this.AddMethods(b,k)}if(b=="TStreamerBase"){k.push({func:function(j,m){var i=j.last_read_version;j.ClassStreamer(m,"TStreamerElement");if(i>2){m.fBaseVersion=j.ntou4()}}});return this.AddMethods(b,k)}if((b=="TStreamerBasicPointer")||(b=="TStreamerLoop")){k.push({func:function(i,j){if(i.last_read_version>1){i.ClassStreamer(j,"TStreamerElement");j.fCountVersion=i.ntou4();j.fCountName=i.ReadTString();j.fCountClass=i.ReadTString()}}});return this.AddMethods(b,k)}if(b=="TStreamerSTL"){k.push({func:function(i,j){if(i.last_read_version>1){i.ClassStreamer(j,"TStreamerElement");j.fSTLtype=i.ntou4();j.fCtype=i.ntou4()}}});return k}if(b=="TStreamerObject"||b=="TStreamerBasicType"||b=="TStreamerObjectAny"||b=="TStreamerString"||b=="TStreamerObjectPointer"){k.push({func:function(i,j){if(i.last_read_version>1){i.ClassStreamer(j,"TStreamerElement")}}});return this.AddMethods(b,k)}if(b=="TStreamerObjectAnyPointer"){k.push({func:function(i,j){if(i.last_read_version>0){i.ClassStreamer(j,"TStreamerElement")}}});return this.AddMethods(b,k)}if(d==null){delete this.fStreamers[b];return null}if(d.fElements===null){return this.AddMethods(b,k)}for(var e=0;e0){f.name="fArray";f.type=a.IO.kAny}else{f.type=a.IO.kBase;this.GetStreamer(h.fName)}}switch(f.type){case a.IO.kBase:f.func=function(i,j){i.ClassStreamer(j,this.name)};break;case a.IO.kTString:f.func=function(i,j){j[this.name]=i.ReadTString()};break;case a.IO.kAnyP:case a.IO.kObjectP:f.func=function(i,j){j[this.name]=i.ReadObjectAny()};break;case a.IO.kOffsetL+a.IO.kBool:case a.IO.kOffsetL+a.IO.kInt:case a.IO.kOffsetL+a.IO.kDouble:case a.IO.kOffsetL+a.IO.kShort:case a.IO.kOffsetL+a.IO.kUShort:case a.IO.kOffsetL+a.IO.kUInt:case a.IO.kOffsetL+a.IO.kULong:case a.IO.kOffsetL+a.IO.kULong64:case a.IO.kOffsetL+a.IO.kLong:case a.IO.kOffsetL+a.IO.kLong64:case a.IO.kOffsetL+a.IO.kFloat:case a.IO.kOffsetL+a.IO.kDouble32:if(h.fArrayDim===1){f.arrlength=h.fArrayLength;f.func=function(i,j){j[this.name]=i.ReadFastArray(this.arrlength,this.type-a.IO.kOffsetL)}}else{if(h.fArrayDim===2){f.arrlength=h.fMaxIndex[1];f.maxindx=h.fMaxIndex[0];f.func=function(i,j){j[this.name]=[];for(var m=0;m0)){q[m]=0;j[m-1].push(j[m]);j[m]=[];++q[--m]}}r[this.name]=j[0]}}}break;case a.IO.kOffsetP+a.IO.kBool:case a.IO.kOffsetP+a.IO.kInt:case a.IO.kOffsetP+a.IO.kDouble:case a.IO.kOffsetP+a.IO.kUChar:case a.IO.kOffsetP+a.IO.kChar:case a.IO.kOffsetP+a.IO.kShort:case a.IO.kOffsetP+a.IO.kUShort:case a.IO.kOffsetP+a.IO.kUInt:case a.IO.kOffsetP+a.IO.kULong:case a.IO.kOffsetP+a.IO.kULong64:case a.IO.kOffsetP+a.IO.kLong:case a.IO.kOffsetP+a.IO.kLong64:case a.IO.kOffsetP+a.IO.kFloat:case a.IO.kOffsetP+a.IO.kDouble32:f.cntname=h.fCountName;f.func=function(i,j){if(i.ntou1()===1){j[this.name]=i.ReadFastArray(j[this.cntname],this.type-a.IO.kOffsetP)}else{j[this.name]=new Array()}};break;case a.IO.kAny:case a.IO.kAnyp:case a.IO.kObjectp:case a.IO.kObject:var c=(h.fTypeName==="BASE")?h.fName:h.fTypeName;if(c.charAt(c.length-1)=="*"){c=c.substr(0,c.length-1)}var l=a.IO.GetArrayKind(c);if(l>0){f.arrkind=l;f.func=function(i,j){j[this.name]=i.ReadFastArray(i.ntou4(),this.arrkind)}}else{if(l===0){f.func=function(i,j){j[this.name]=i.ReadTString()}}else{f.classname=c;f.func=function(i,j){j[this.name]=i.ClassStreamer({},this.classname)}}}break;case a.IO.kOffsetL+a.IO.kObject:case a.IO.kOffsetL+a.IO.kAny:case a.IO.kOffsetL+a.IO.kAnyp:case a.IO.kOffsetL+a.IO.kObjectp:f.arrlength=h.fArrayLength;var c=h.fTypeName;if(c.charAt(c.length-1)=="*"){c=c.substr(0,c.length-1)}var l=a.IO.GetArrayKind(c);if(l>0){f.arrkind=l;f.func=function(j,m){m[this.name]=[];for(var i=0;i"){t=j.ReadFastArray(j.ntoi4(),a.IO.kDouble)}else{if(this.typename=="vector"){t=j.ReadFastArray(j.ntoi4(),a.IO.kInt)}else{if(this.typename=="vector"){t=j.ReadFastArray(j.ntoi4(),a.IO.kFloat)}else{if(this.typename=="vector"){var o=j.ntoi4();t=[];for(var r=0;rJSROOT version " + JSROOT.version + "

" + + '

Hierarchy in json and xml format

' + + ' Monitoring ' + + ' '; + } else { + + var files = myDiv.attr("files"); + var path = JSROOT.GetUrlOption("path"); + if (path==null) path = myDiv.attr("path"); + if (path==null) path = ""; + + if (files==null) files = "../files/hsimple.root"; + var arrFiles = files.split(';'); + + guiCode += "

Read a ROOT file

" + + "

JSROOT version " + JSROOT.version + "

"; + + if (JSROOT.GetUrlOption("noselect")==null) { + guiCode += '
' + +'' + +'
' + +'

Read docu' + +' how to open files from other servers.

' + +'' + +'' + +'
' + +'
'; + } + } + + guiCode += '
' + +'' + +'
' + +'
'; + + var drawDivId = 'right-div'; + + myDiv.empty().append(guiCode); + + var h0 = null; + + if (online) { + if (typeof GetCachedHierarchy == 'function') h0 = GetCachedHierarchy(); + if (typeof h0 != 'object') h0 = ""; + } + + hpainter = new JSROOT.HierarchyPainter('root', 'browser'); + + hpainter.SetDisplay(null, drawDivId); + + JSROOT.Painter.ConfigureVSeparator(hpainter); + + // JSROOT.Painter.ConfigureHSeparator(28, true); + + hpainter.StartGUI(h0, function() { + + setGuiLayout(hpainter.GetLayout()); + + // specify display kind every time selection done + // will be actually used only for first drawing or after reset + $("#layout").change(function() { + if (hpainter) hpainter.SetDisplay(guiLayout(), drawDivId); + }); + + if (online) { + if ((hpainter.h!=null) && ('_toptitle' in hpainter.h)) + $("#toptitle").html(hpainter.h._toptitle); + $("#monitoring") + .prop('checked', hpainter.IsMonitoring()) + .click(function() { + hpainter.EnableMonitoring(this.checked); + hpainter.updateAll(!this.checked); + }); + } else { + var fname = ""; + hpainter.ForEachRootFile(function(item) { if (fname=="") fname = item._fullurl; }); + $("#urlToLoad").val(fname); + } + }); + } + + return JSROOT; + +})); + diff --git a/visualisations/JsRoot460/scripts/JSRootInterface.min.js b/visualisations/JsRoot460/scripts/JSRootInterface.min.js new file mode 100644 index 0000000..e1984cd --- /dev/null +++ b/visualisations/JsRoot460/scripts/JSRootInterface.min.js @@ -0,0 +1 @@ +(function(a){if(typeof define==="function"&&define.amd){define(["jquery","jquery-ui","d3","JSRootPainter"],a)}else{if(typeof jQuery=="undefined"){throw new Error("jQuery not defined","JSRootPainter.jquery.js")}if(typeof jQuery.ui=="undefined"){throw new Error("jQuery-ui not defined","JSRootPainter.jquery.js")}if(typeof d3!="object"){throw new Error("This extension requires d3.v3.js","JSRootPainter.jquery.js")}if(typeof JSROOT=="undefined"){throw new Error("JSROOT is not defined","JSRootPainter.jquery.js")}if(typeof JSROOT.Painter!="object"){throw new Error("JSROOT.Painter not defined","JSRootPainter.jquery.js")}a(jQuery,jQuery.ui,d3,JSROOT)}}(function(d,e,b,a){var c=null;if(typeof define==="function"&&define.amd){a.loadScript("$$$style/JSRootInterface.css")}ResetUI=function(){if(c){c.clear(true)}};guiLayout=function(){var g="collapsible";var f=document.getElementById("layout");if(f){g=f.options[f.selectedIndex].text}return g};setGuiLayout=function(j){var g=document.getElementById("layout");if(!g){return}for(var f in g.options){var h=g.options[f].text;if(typeof h=="undefined"){continue}if((h==j)||(h.replace(/ /g,"")==j)){g.selectedIndex=f;break}}};ReadFile=function(){var f=d("#urlToLoad").val();f.trim();if(f.length==0){return}if(c==null){alert("Hierarchy painter not initialized")}if((f.lastIndexOf(".json")==f.length-5)||(f.lastIndexOf(".JSON")==f.length-5)){c.OpenJsonFile(f)}else{c.OpenRootFile(f)}};BuildSimpleGUI=function(){if(a.GetUrlOption("nobrowser")!=null){return a.BuildNobrowserGUI()}var g=d("#simpleGUI");var l=false;if(g.length==0){g=d("#onlineGUI");if(g.length==0){return alert("no div for simple gui found")}l=true}a.Painter.readStyleFromURL();var h="
";if(l){h+="

ROOT online server

JSROOT version "+a.version+'

Hierarchy in json and xml format

Monitoring '}else{var f=g.attr("files");var o=a.GetUrlOption("path");if(o==null){o=g.attr("path")}if(o==null){o=""}if(f==null){f="../files/hsimple.root"}var j=f.split(";");h+="

Read a ROOT file

JSROOT version "+a.version+"

";if(a.GetUrlOption("noselect")==null){h+='

Read docu how to open files from other servers.


'}}h+='
';var m="right-div";g.empty().append(h);var n=null;if(l){if(typeof GetCachedHierarchy=="function"){n=GetCachedHierarchy()}if(typeof n!="object"){n=""}}c=new a.HierarchyPainter("root","browser");c.SetDisplay(null,m);a.Painter.ConfigureVSeparator(c);c.StartGUI(n,function(){setGuiLayout(c.GetLayout());d("#layout").change(function(){if(c){c.SetDisplay(guiLayout(),m)}});if(l){if((c.h!=null)&&("_toptitle" in c.h)){d("#toptitle").html(c.h._toptitle)}d("#monitoring").prop("checked",c.IsMonitoring()).click(function(){c.EnableMonitoring(this.checked);c.updateAll(!this.checked)})}else{var i="";c.ForEachRootFile(function(p){if(i==""){i=p._fullurl}});d("#urlToLoad").val(i)}})};return a})); \ No newline at end of file diff --git a/visualisations/JsRoot460/scripts/JSRootMath.js b/visualisations/JsRoot460/scripts/JSRootMath.js new file mode 100644 index 0000000..267cc25 --- /dev/null +++ b/visualisations/JsRoot460/scripts/JSRootMath.js @@ -0,0 +1,623 @@ +/** @file JSRootMath.js + * Special mathematical functions */ + +/** @namespace JSROOT.Math + * Holder of mathematical functions, analogue to TMath class of ROOT */ + +(function( factory ) { + if ( typeof define === "function" && define.amd ) { + // AMD. Register as an anonymous module. + define( ['JSRootCore'], factory ); + } else { + if (typeof JSROOT == 'undefined') + throw new Error("This extension requires JSRootCore.js", "JSRootMath.js"); + + if (typeof JSROOT.Math == "object") + throw new Error("This JSROOT Math already loaded", "JSRootMath.js"); + + factory(JSROOT); + } +} (function(JSROOT) { + // math methods for Javascript ROOT + + JSROOT.Math = {}; + + /** @memberOf JSROOT.Math */ + JSROOT.Math.lgam = function( x ) { + var p, q, u, w, z, i, sgngam = 1; + var kMAXLGM = 2.556348e305; + var LS2PI = 0.91893853320467274178; + + var A = [ + 8.11614167470508450300E-4, + -5.95061904284301438324E-4, + 7.93650340457716943945E-4, + -2.77777777730099687205E-3, + 8.33333333333331927722E-2 + ]; + + var B = [ + -1.37825152569120859100E3, + -3.88016315134637840924E4, + -3.31612992738871184744E5, + -1.16237097492762307383E6, + -1.72173700820839662146E6, + -8.53555664245765465627E5 + ]; + + var C = [ + /* 1.00000000000000000000E0, */ + -3.51815701436523470549E2, + -1.70642106651881159223E4, + -2.20528590553854454839E5, + -1.13933444367982507207E6, + -2.53252307177582951285E6, + -2.01889141433532773231E6 + ]; + + if (x >= Number.POSITIVE_INFINITY) + return(Number.POSITIVE_INFINITY); + + if ( x < -34.0 ) { + q = -x; + w = this.lgam(q); + p = Math.floor(q); + if ( p==q )//_unur_FP_same(p,q) + return (Number.POSITIVE_INFINITY); + i = Math.round(p); + if ( (i & 1) == 0 ) + sgngam = -1; + else + sgngam = 1; + z = q - p; + if ( z > 0.5 ) { + p += 1.0; + z = p - q; + } + z = q * Math.sin( Math.PI * z ); + if ( z < 1e-300 ) + return (Number.POSITIVE_INFINITY); + z = Math.log(Math.PI) - Math.log( z ) - w; + return( z ); + } + if ( x < 13.0 ) { + z = 1.0; + p = 0.0; + u = x; + while ( u >= 3.0 ) { + p -= 1.0; + u = x + p; + z *= u; + } + while ( u < 2.0 ) { + if ( u < 1e-300 ) + return (Number.POSITIVE_INFINITY); + z /= u; + p += 1.0; + u = x + p; + } + if ( z < 0.0 ) { + sgngam = -1; + z = -z; + } + else + sgngam = 1; + if ( u == 2.0 ) + return( Math.log(z) ); + p -= 2.0; + x = x + p; + p = x * this.Polynomialeval(x, B, 5 ) / this.Polynomial1eval( x, C, 6); + return( Math.log(z) + p ); + } + if ( x > kMAXLGM ) + return( sgngam * Number.POSITIVE_INFINITY ); + + q = ( x - 0.5 ) * Math.log(x) - x + LS2PI; + if ( x > 1.0e8 ) + return( q ); + + p = 1.0/(x*x); + if ( x >= 1000.0 ) + q += ((7.9365079365079365079365e-4 * p + - 2.7777777777777777777778e-3) *p + + 0.0833333333333333333333) / x; + else + q += this.Polynomialeval( p, A, 4 ) / x; + return( q ); + }; + + /** + * calculates a value of a polynomial of the form: + * a[0]x^N+a[1]x^(N-1) + ... + a[N] + * + * @memberOf JSROOT.Math + */ + JSROOT.Math.Polynomialeval = function(x, a, N) { + if (N==0) return a[0]; + else { + var pom = a[0]; + for (var i=1; i <= N; ++i) + pom = pom *x + a[i]; + return pom; + } + }; + + /** + * calculates a value of a polynomial of the form: + * x^N+a[0]x^(N-1) + ... + a[N-1] + * + * @memberOf JSROOT.Math + */ + JSROOT.Math.Polynomial1eval = function(x, a, N) { + if (N==0) return a[0]; + else { + var pom = x + a[0]; + for (var i=1; i < N; ++i) + pom = pom *x + a[i]; + return pom; + } + }; + + /** @memberOf JSROOT.Math */ + JSROOT.Math.ndtri = function( y0 ) { + if ( y0 <= 0.0 ) + return( Number.NEGATIVE_INFINITY ); + if ( y0 >= 1.0 ) + return( Number.POSITIVE_INFINITY ); + + var P0 = new Array( + -5.99633501014107895267E1, + 9.80010754185999661536E1, + -5.66762857469070293439E1, + 1.39312609387279679503E1, + -1.23916583867381258016E0 + ); + + var Q0 = new Array( + 1.95448858338141759834E0, + 4.67627912898881538453E0, + 8.63602421390890590575E1, + -2.25462687854119370527E2, + 2.00260212380060660359E2, + -8.20372256168333339912E1, + 1.59056225126211695515E1, + -1.18331621121330003142E0 + ); + + var P1 = new Array( + 4.05544892305962419923E0, + 3.15251094599893866154E1, + 5.71628192246421288162E1, + 4.40805073893200834700E1, + 1.46849561928858024014E1, + 2.18663306850790267539E0, + -1.40256079171354495875E-1, + -3.50424626827848203418E-2, + -8.57456785154685413611E-4 + ); + + var Q1 = new Array( + 1.57799883256466749731E1, + 4.53907635128879210584E1, + 4.13172038254672030440E1, + 1.50425385692907503408E1, + 2.50464946208309415979E0, + -1.42182922854787788574E-1, + -3.80806407691578277194E-2, + -9.33259480895457427372E-4 + ); + + var P2 = new Array( + 3.23774891776946035970E0, + 6.91522889068984211695E0, + 3.93881025292474443415E0, + 1.33303460815807542389E0, + 2.01485389549179081538E-1, + 1.23716634817820021358E-2, + 3.01581553508235416007E-4, + 2.65806974686737550832E-6, + 6.23974539184983293730E-9 + ); + + var Q2 = new Array( + 6.02427039364742014255E0, + 3.67983563856160859403E0, + 1.37702099489081330271E0, + 2.16236993594496635890E-1, + 1.34204006088543189037E-2, + 3.28014464682127739104E-4, + 2.89247864745380683936E-6, + 6.79019408009981274425E-9 + ); + + var s2pi = 2.50662827463100050242e0; + var code = 1; + var y = y0; + var x, z, y2, x0, x1; + + if ( y > (1.0 - 0.13533528323661269189) ) { + y = 1.0 - y; + code = 0; + } + if ( y > 0.13533528323661269189 ) { + y = y - 0.5; + y2 = y * y; + x = y + y * (y2 * this.Polynomialeval( y2, P0, 4)/ this.Polynomial1eval( y2, Q0, 8 )); + x = x * s2pi; + return(x); + } + x = Math.sqrt( -2.0 * Math.log(y) ); + x0 = x - Math.log(x)/x; + z = 1.0/x; + if ( x < 8.0 ) + x1 = z * this.Polynomialeval( z, P1, 8 )/ this.Polynomial1eval( z, Q1, 8 ); + else + x1 = z * this.Polynomialeval( z, P2, 8 )/ this.Polynomial1eval( z, Q2, 8 ); + x = x0 - x1; + if ( code != 0 ) + x = -x; + return( x ); + } + + /** @memberOf JSROOT.Math */ + JSROOT.Math.igam = function(a,x) { + var kMACHEP = 1.11022302462515654042363166809e-16; + var kMAXLOG = 709.782712893383973096206318587; + var ans, ax, c, r; + + // LM: for negative values returns 1.0 instead of zero + // This is correct if a is a negative integer since Gamma(-n) = +/- inf + if (a <= 0) return 1.0; + + if (x <= 0) return 0.0; + + if( (x > 1.0) && (x > a ) ) + return( 1.0 - this.igamc(a,x) ); + + /* Compute x**a * exp(-x) / gamma(a) */ + ax = a * Math.log(x) - x - this.lgam(a); + if( ax < -kMAXLOG ) + return( 0.0 ); + + ax = Math.exp(ax); + + /* power series */ + r = a; + c = 1.0; + ans = 1.0; + + do + { + r += 1.0; + c *= x/r; + ans += c; + } + while( c/ans > kMACHEP ); + + return( ans * ax/a ); + } + + /** @memberOf JSROOT.Math */ + JSROOT.Math.igamc = function(a,x) { + var kMACHEP = 1.11022302462515654042363166809e-16; + var kMAXLOG = 709.782712893383973096206318587; + + var kBig = 4.503599627370496e15; + var kBiginv = 2.22044604925031308085e-16; + + var ans, ax, c, yc, r, t, y, z; + var pk, pkm1, pkm2, qk, qkm1, qkm2; + + // LM: for negative values returns 0.0 + // This is correct if a is a negative integer since Gamma(-n) = +/- inf + if (a <= 0) return 0.0; + + if (x <= 0) return 1.0; + + if( (x < 1.0) || (x < a) ) + return ( 1.0 - JSROOT.Math.igam(a,x) ); + + ax = a * Math.log(x) - x - JSROOT.Math.lgam(a); + if( ax < -kMAXLOG ) + return( 0.0 ); + + ax = Math.exp(ax); + + /* continued fraction */ + y = 1.0 - a; + z = x + y + 1.0; + c = 0.0; + pkm2 = 1.0; + qkm2 = x; + pkm1 = x + 1.0; + qkm1 = z * x; + ans = pkm1/qkm1; + + do + { + c += 1.0; + y += 1.0; + z += 2.0; + yc = y * c; + pk = pkm1 * z - pkm2 * yc; + qk = qkm1 * z - qkm2 * yc; + if(qk) + { + r = pk/qk; + t = Math.abs( (ans - r)/r ); + ans = r; + } + else + t = 1.0; + pkm2 = pkm1; + pkm1 = pk; + qkm2 = qkm1; + qkm1 = qk; + if( Math.abs(pk) > kBig ) + { + pkm2 *= kBiginv; + pkm1 *= kBiginv; + qkm2 *= kBiginv; + qkm1 *= kBiginv; + } + } + while( t > kMACHEP ); + + return( ans * ax ); + } + + + /** @memberOf JSROOT.Math */ + JSROOT.Math.igami = function(a, y0) { + var x0, x1, x, yl, yh, y, d, lgm, dithresh; + var i, dir; + var kMACHEP = 1.11022302462515654042363166809e-16; + + // check the domain + if (a <= 0) { + alert("igami : Wrong domain for parameter a (must be > 0)"); + return 0; + } + if (y0 <= 0) { + return Number.POSITIVE_INFINITY; + } + if (y0 >= 1) { + return 0; + } + /* bound the solution */ + var kMAXNUM = Number.MAX_VALUE; + x0 = kMAXNUM; + yl = 0; + x1 = 0; + yh = 1.0; + dithresh = 5.0 * kMACHEP; + + /* approximation to inverse function */ + d = 1.0/(9.0*a); + y = ( 1.0 - d - this.ndtri(y0) * Math.sqrt(d) ); + x = a * y * y * y; + + lgm = this.lgam(a); + + for( i=0; i<10; ++i ) { + if ( x > x0 || x < x1 ) + break; + y = this.igamc(a,x); + if ( y < yl || y > yh ) + break; + if ( y < y0 ) { + x0 = x; + yl = y; + } + else { + x1 = x; + yh = y; + } + /* compute the derivative of the function at this point */ + d = (a - 1.0) * Math.log(x) - x - lgm; + if ( d < -kMAXLOG ) + break; + d = -Math.exp(d); + /* compute the step to the next approximation of x */ + d = (y - y0)/d; + if ( Math.abs(d/x) < kMACHEP ) + return( x ); + x = x - d; + } + /* Resort to interval halving if Newton iteration did not converge. */ + d = 0.0625; + if ( x0 == kMAXNUM ) { + if ( x <= 0.0 ) + x = 1.0; + while ( x0 == kMAXNUM ) { + x = (1.0 + d) * x; + y = this.igamc( a, x ); + if ( y < y0 ) { + x0 = x; + yl = y; + break; + } + d = d + d; + } + } + d = 0.5; + dir = 0; + + for( i=0; i<400; ++i ) { + x = x1 + d * (x0 - x1); + y = this.igamc( a, x ); + lgm = (x0 - x1)/(x1 + x0); + if ( Math.abs(lgm) < dithresh ) + break; + lgm = (y - y0)/y0; + if ( Math.abs(lgm) < dithresh ) + break; + if ( x <= 0.0 ) + break; + if ( y >= y0 ) { + x1 = x; + yh = y; + if ( dir < 0 ) { + dir = 0; + d = 0.5; + } + else if ( dir > 1 ) + d = 0.5 * d + 0.5; + else + d = (y0 - yl)/(yh - yl); + dir += 1; + } + else { + x0 = x; + yl = y; + if ( dir > 0 ) { + dir = 0; + d = 0.5; + } + else if ( dir < -1 ) + d = 0.5 * d; + else + d = (y0 - yl)/(yh - yl); + dir -= 1; + } + } + return( x ); + }; + + /** @memberOf JSROOT.Math */ + JSROOT.Math.gamma_quantile_c = function(z, alpha, theta) { + return theta * this.igami( alpha, z); + }; + + /** @memberOf JSROOT.Math */ + JSROOT.Math.gamma_quantile = function(z, alpha, theta) { + return theta * this.igami( alpha, 1.- z); + }; + + /** @memberOf JSROOT.Math */ + JSROOT.Math.log10 = function(n) { + return Math.log(n) / Math.log(10); + }; + + /** @memberOf JSROOT.Math */ + JSROOT.Math.landau_pdf = function(x, xi, x0) { + // LANDAU pdf : algorithm from CERNLIB G110 denlan + // same algorithm is used in GSL + if (xi <= 0) return 0; + var v = (x - x0)/xi; + var u, ue, us, denlan; + var p1 = new Array(0.4259894875,-0.1249762550, 0.03984243700, -0.006298287635, 0.001511162253); + var q1 = new Array(1.0 ,-0.3388260629, 0.09594393323, -0.01608042283, 0.003778942063); + var p2 = new Array(0.1788541609, 0.1173957403, 0.01488850518, -0.001394989411, 0.0001283617211); + var q2 = new Array(1.0 , 0.7428795082, 0.3153932961, 0.06694219548, 0.008790609714); + var p3 = new Array(0.1788544503, 0.09359161662,0.006325387654, 0.00006611667319,-0.000002031049101); + var q3 = new Array(1.0 , 0.6097809921, 0.2560616665, 0.04746722384, 0.006957301675); + var p4 = new Array(0.9874054407, 118.6723273, 849.2794360, -743.7792444, 427.0262186); + var q4 = new Array(1.0 , 106.8615961, 337.6496214, 2016.712389, 1597.063511); + var p5 = new Array(1.003675074, 167.5702434, 4789.711289, 21217.86767, -22324.94910); + var q5 = new Array(1.0 , 156.9424537, 3745.310488, 9834.698876, 66924.28357); + var p6 = new Array(1.000827619, 664.9143136, 62972.92665, 475554.6998, -5743609.109); + var q6 = new Array(1.0 , 651.4101098, 56974.73333, 165917.4725, -2815759.939); + var a1 = new Array(0.04166666667,-0.01996527778, 0.02709538966); + var a2 = new Array(-1.845568670,-4.284640743); + + if (v < -5.5) { + u = Math.exp(v+1.0); + if (u < 1e-10) return 0.0; + ue = Math.exp(-1/u); + us = Math.sqrt(u); + denlan = 0.3989422803*(ue/us)*(1+(a1[0]+(a1[1]+a1[2]*u)*u)*u); + } else if(v < -1) { + u = Math.exp(-v-1); + denlan = Math.exp(-u)*Math.sqrt(u)* + (p1[0]+(p1[1]+(p1[2]+(p1[3]+p1[4]*v)*v)*v)*v)/ + (q1[0]+(q1[1]+(q1[2]+(q1[3]+q1[4]*v)*v)*v)*v); + } else if(v < 1) { + denlan = (p2[0]+(p2[1]+(p2[2]+(p2[3]+p2[4]*v)*v)*v)*v)/ + (q2[0]+(q2[1]+(q2[2]+(q2[3]+q2[4]*v)*v)*v)*v); + } else if(v < 5) { + denlan = (p3[0]+(p3[1]+(p3[2]+(p3[3]+p3[4]*v)*v)*v)*v)/ + (q3[0]+(q3[1]+(q3[2]+(q3[3]+q3[4]*v)*v)*v)*v); + } else if(v < 12) { + u = 1/v; + denlan = u*u*(p4[0]+(p4[1]+(p4[2]+(p4[3]+p4[4]*u)*u)*u)*u)/ + (q4[0]+(q4[1]+(q4[2]+(q4[3]+q4[4]*u)*u)*u)*u); + } else if(v < 50) { + u = 1/v; + denlan = u*u*(p5[0]+(p5[1]+(p5[2]+(p5[3]+p5[4]*u)*u)*u)*u)/ + (q5[0]+(q5[1]+(q5[2]+(q5[3]+q5[4]*u)*u)*u)*u); + } else if(v < 300) { + u = 1/v; + denlan = u*u*(p6[0]+(p6[1]+(p6[2]+(p6[3]+p6[4]*u)*u)*u)*u)/ + (q6[0]+(q6[1]+(q6[2]+(q6[3]+q6[4]*u)*u)*u)*u); + } else { + u = 1/(v-v*Math.log(v)/(v+1)); + denlan = u*u*(1+(a2[0]+a2[1]*u)*u); + } + return denlan/xi; + }; + + /** @memberOf JSROOT.Math */ + JSROOT.Math.Landau = function(x, mpv, sigma, norm) { + if (sigma <= 0) return 0; + var den = JSROOT.Math.landau_pdf((x - mpv) / sigma, 1, 0); + if (!norm) return den; + return den/sigma; + } + + /** @memberOf JSROOT.Math */ + JSROOT.Math.inc_gamma_c = function(a,x) { + return JSROOT.Math.igamc(a,x); + } + + /** @memberOf JSROOT.Math */ + JSROOT.Math.chisquared_cdf_c = function(x,r,x0) { + return JSROOT.Math.inc_gamma_c ( 0.5 * r , 0.5* (x-x0) ); + }; + + /** @memberOf JSROOT.Math */ + JSROOT.Math.Prob = function(chi2, ndf) { + if (ndf <= 0) return 0; // Set CL to zero in case ndf<=0 + + if (chi2 <= 0) { + if (chi2 < 0) return 0; + else return 1; + } + + return JSROOT.Math.chisquared_cdf_c(chi2,ndf,0); + }; + + /** @memberOf JSROOT.Math */ + JSROOT.Math.Gaus = function(x, mean, sigma) { + return Math.exp(-0.5 * Math.pow((x-mean) / sigma, 2)); + }; + + /** @memberOf JSROOT.Math */ + JSROOT.Math.gaus = function(f, x, i) { + // function used when gaus(0) used in the TFormula + return f.GetParValue(i+0) * Math.exp(-0.5 * Math.pow((x-f.GetParValue(i+1)) / f.GetParValue(i+2), 2)); + }; + + /** @memberOf JSROOT.Math */ + JSROOT.Math.gausn = function(f, x, i) { + return JSROOT.Math.gaus(f, x, i)/(Math.sqrt(2 * Math.PI) * f.GetParValue(i+2)); + }; + + /** @memberOf JSROOT.Math */ + JSROOT.Math.expo = function(f, x, i) { + return Math.exp(f.GetParValue(i+0) + f.GetParValue(i+1) * x); + }; + + /** @memberOf JSROOT.Math */ + JSROOT.Math.landau = function(f, x, i) { + return JSROOT.Math.Landau(x, f.GetParValue(i+1),f.GetParValue(i+2), false); + }; + + /** @memberOf JSROOT.Math */ + JSROOT.Math.landaun = function(f, x, i) { + return JSROOT.Math.Landau(x, f.GetParValue(i+1),f.GetParValue(i+2), true); + }; + + return JSROOT; + +})); diff --git a/visualisations/JsRoot460/scripts/JSRootMath.min.js b/visualisations/JsRoot460/scripts/JSRootMath.min.js new file mode 100644 index 0000000..54ccb87 --- /dev/null +++ b/visualisations/JsRoot460/scripts/JSRootMath.min.js @@ -0,0 +1 @@ +(function(a){if(typeof define==="function"&&define.amd){define(["JSRootCore"],a)}else{if(typeof JSROOT=="undefined"){throw new Error("This extension requires JSRootCore.js","JSRootMath.js")}if(typeof JSROOT.Math=="object"){throw new Error("This JSROOT Math already loaded","JSRootMath.js")}a(JSROOT)}}(function(a){a.Math={};a.Math.lgam=function(m){var e,c,o,n,l,g,h=1;var j=2.556348e+305;var k=0.9189385332046728;var f=[0.0008116141674705085,-0.0005950619042843014,0.0007936503404577169,-0.002777777777300997,0.08333333333333319];var d=[-1378.2515256912086,-38801.631513463784,-331612.9927388712,-1162370.974927623,-1721737.0082083966,-853555.6642457654];var b=[-351.81570143652345,-17064.210665188115,-220528.59055385445,-1139334.4436798252,-2532523.0717758294,-2018891.4143353277];if(m>=Number.POSITIVE_INFINITY){return(Number.POSITIVE_INFINITY)}if(m<-34){c=-m;n=this.lgam(c);e=Math.floor(c);if(e==c){return(Number.POSITIVE_INFINITY)}g=Math.round(e);if((g&1)==0){h=-1}else{h=1}l=c-e;if(l>0.5){e+=1;l=e-c}l=c*Math.sin(Math.PI*l);if(l<1e-300){return(Number.POSITIVE_INFINITY)}l=Math.log(Math.PI)-Math.log(l)-n;return(l)}if(m<13){l=1;e=0;o=m;while(o>=3){e-=1;o=m+e;l*=o}while(o<2){if(o<1e-300){return(Number.POSITIVE_INFINITY)}l/=o;e+=1;o=m+e}if(l<0){h=-1;l=-l}else{h=1}if(o==2){return(Math.log(l))}e-=2;m=m+e;e=m*this.Polynomialeval(m,d,5)/this.Polynomial1eval(m,b,6);return(Math.log(l)+e)}if(m>j){return(h*Number.POSITIVE_INFINITY)}c=(m-0.5)*Math.log(m)-m+k;if(m>100000000){return(c)}e=1/(m*m);if(m>=1000){c+=((0.0007936507936507937*e-0.002777777777777778)*e+0.08333333333333333)/m}else{c+=this.Polynomialeval(e,f,4)/m}return(c)};a.Math.Polynomialeval=function(b,c,f){if(f==0){return c[0]}else{var e=c[0];for(var d=1;d<=f;++d){e=e*b+c[d]}return e}};a.Math.Polynomial1eval=function(b,c,f){if(f==0){return c[0]}else{var e=b+c[0];for(var d=1;d=1){return(Number.POSITIVE_INFINITY)}var c=new Array(-59.96335010141079,98.00107541859997,-56.67628574690703,13.931260938727968,-1.2391658386738125);var m=new Array(1.9544885833814176,4.676279128988815,86.36024213908905,-225.46268785411937,200.26021238006066,-82.03722561683334,15.90562251262117,-1.1833162112133);var b=new Array(4.0554489230596245,31.525109459989388,57.16281922464213,44.08050738932008,14.684956192885803,2.1866330685079025,-0.1402560791713545,-0.03504246268278482,-0.0008574567851546854);var j=new Array(15.779988325646675,45.39076351288792,41.3172038254672,15.04253856929075,2.504649462083094,-0.14218292285478779,-0.03808064076915783,-0.0009332594808954574);var p=new Array(3.2377489177694603,6.915228890689842,3.9388102529247444,1.3330346081580755,0.20148538954917908,0.012371663481782003,0.00030158155350823543,0.0000026580697468673755,6.239745391849833e-9);var h=new Array(6.02427039364742,3.6798356385616087,1.3770209948908132,0.21623699359449663,0.013420400608854318,0.00032801446468212774,0.0000028924786474538068,6.790194080099813e-9);var g=2.5066282746310007;var e=1;var l=o;var n,i,k,f,d;if(l>(1-0.1353352832366127)){l=1-l;e=0}if(l>0.1353352832366127){l=l-0.5;k=l*l;n=l+l*(k*this.Polynomialeval(k,c,4)/this.Polynomial1eval(k,m,8));n=n*g;return(n)}n=Math.sqrt(-2*Math.log(l));f=n-Math.log(n)/n;i=1/n;if(n<8){d=i*this.Polynomialeval(i,b,8)/this.Polynomial1eval(i,j,8)}else{d=i*this.Polynomialeval(i,p,8)/this.Polynomial1eval(i,h,8)}n=f-d;if(e!=0){n=-n}return(n)};a.Math.igam=function(d,b){var i=1.1102230246251565e-16;var f=709.782712893384;var e,h,j,g;if(d<=0){return 1}if(b<=0){return 0}if((b>1)&&(b>d)){return(1-this.igamc(d,b))}h=d*Math.log(b)-b-this.lgam(d);if(h<-f){return(0)}h=Math.exp(h);g=d;j=1;e=1;do{g+=1;j*=b/g;e+=j}while(j/e>i);return(e*h/d)};a.Math.igamc=function(w,l){var f=1.1102230246251565e-16;var b=709.782712893384;var A=4503599627370496;var h=2.220446049250313e-16;var p,m,s,g,o,n,k,j;var q,v,u,i,e,d;if(w<=0){return 0}if(l<=0){return 1}if((l<1)||(lA){u*=h;v*=h;d*=h;e*=h}}while(n>f);return(p*m)};a.Math.igami=function(o,q){var e,c,p,f,j,n,l,r,h;var k,g;var m=1.1102230246251565e-16;if(o<=0){alert("igami : Wrong domain for parameter a (must be > 0)");return 0}if(q<=0){return Number.POSITIVE_INFINITY}if(q>=1){return 0}var b=Number.MAX_VALUE;e=b;f=0;c=0;j=1;h=5*m;l=1/(9*o);n=(1-l-this.ndtri(q)*Math.sqrt(l));p=o*n*n*n;r=this.lgam(o);for(k=0;k<10;++k){if(p>e||pj){break}if(n=q){c=p;j=n;if(g<0){g=0;l=0.5}else{if(g>1){l=0.5*l+0.5}else{l=(q-f)/(j-f)}}g+=1}else{e=p;f=n;if(g>0){g=0;l=0.5}else{if(g<-1){l=0.5*l}else{l=(q-f)/(j-f)}}g-=1}}return(p)};a.Math.gamma_quantile_c=function(d,c,b){return b*this.igami(c,d)};a.Math.gamma_quantile=function(d,c,b){return b*this.igami(c,1-d)};a.Math.log10=function(b){return Math.log(b)/Math.log(10)};a.Math.landau_pdf=function(n,q,s){if(q<=0){return 0}var o=(n-s)/q;var p,r,k,h;var e=new Array(0.4259894875,-0.124976255,0.039842437,-0.006298287635,0.001511162253);var m=new Array(1,-0.3388260629,0.09594393323,-0.01608042283,0.003778942063);var d=new Array(0.1788541609,0.1173957403,0.01488850518,-0.001394989411,0.0001283617211);var l=new Array(1,0.7428795082,0.3153932961,0.06694219548,0.008790609714);var c=new Array(0.1788544503,0.09359161662,0.006325387654,0.00006611667319,-0.000002031049101);var j=new Array(1,0.6097809921,0.2560616665,0.04746722384,0.006957301675);var b=new Array(0.9874054407,118.6723273,849.279436,-743.7792444,427.0262186);var i=new Array(1,106.8615961,337.6496214,2016.712389,1597.063511);var z=new Array(1.003675074,167.5702434,4789.711289,21217.86767,-22324.9491);var g=new Array(1,156.9424537,3745.310488,9834.698876,66924.28357);var y=new Array(1.000827619,664.9143136,62972.92665,475554.6998,-5743609.109);var f=new Array(1,651.4101098,56974.73333,165917.4725,-2815759.939);var w=new Array(0.04166666667,-0.01996527778,0.02709538966);var t=new Array(-1.84556867,-4.284640743);if(o<-5.5){p=Math.exp(o+1);if(p<1e-10){return 0}r=Math.exp(-1/p);k=Math.sqrt(p);h=0.3989422803*(r/k)*(1+(w[0]+(w[1]+w[2]*p)*p)*p)}else{if(o<-1){p=Math.exp(-o-1);h=Math.exp(-p)*Math.sqrt(p)*(e[0]+(e[1]+(e[2]+(e[3]+e[4]*o)*o)*o)*o)/(m[0]+(m[1]+(m[2]+(m[3]+m[4]*o)*o)*o)*o)}else{if(o<1){h=(d[0]+(d[1]+(d[2]+(d[3]+d[4]*o)*o)*o)*o)/(l[0]+(l[1]+(l[2]+(l[3]+l[4]*o)*o)*o)*o)}else{if(o<5){h=(c[0]+(c[1]+(c[2]+(c[3]+c[4]*o)*o)*o)*o)/(j[0]+(j[1]+(j[2]+(j[3]+j[4]*o)*o)*o)*o)}else{if(o<12){p=1/o;h=p*p*(b[0]+(b[1]+(b[2]+(b[3]+b[4]*p)*p)*p)*p)/(i[0]+(i[1]+(i[2]+(i[3]+i[4]*p)*p)*p)*p)}else{if(o<50){p=1/o;h=p*p*(z[0]+(z[1]+(z[2]+(z[3]+z[4]*p)*p)*p)*p)/(g[0]+(g[1]+(g[2]+(g[3]+g[4]*p)*p)*p)*p)}else{if(o<300){p=1/o;h=p*p*(y[0]+(y[1]+(y[2]+(y[3]+y[4]*p)*p)*p)*p)/(f[0]+(f[1]+(f[2]+(f[3]+f[4]*p)*p)*p)*p)}else{p=1/(o-o*Math.log(o)/(o+1));h=p*p*(1+(t[0]+t[1]*p)*p)}}}}}}}return h/q};a.Math.Landau=function(b,f,d,c){if(d<=0){return 0}var e=a.Math.landau_pdf((b-f)/d,1,0);if(!c){return e}return e/d};a.Math.inc_gamma_c=function(c,b){return a.Math.igamc(c,b)};a.Math.chisquared_cdf_c=function(b,d,c){return a.Math.inc_gamma_c(0.5*d,0.5*(b-c))};a.Math.Prob=function(b,c){if(c<=0){return 0}if(b<=0){if(b<0){return 0}else{return 1}}return a.Math.chisquared_cdf_c(b,c,0)};a.Math.Gaus=function(b,c,d){return Math.exp(-0.5*Math.pow((b-c)/d,2))};a.Math.gaus=function(d,b,c){return d.GetParValue(c+0)*Math.exp(-0.5*Math.pow((b-d.GetParValue(c+1))/d.GetParValue(c+2),2))};a.Math.gausn=function(d,b,c){return a.Math.gaus(d,b,c)/(Math.sqrt(2*Math.PI)*d.GetParValue(c+2))};a.Math.expo=function(d,b,c){return Math.exp(d.GetParValue(c+0)+d.GetParValue(c+1)*b)};a.Math.landau=function(d,b,c){return a.Math.Landau(b,d.GetParValue(c+1),d.GetParValue(c+2),false)};a.Math.landaun=function(d,b,c){return a.Math.Landau(b,d.GetParValue(c+1),d.GetParValue(c+2),true)};return a})); \ No newline at end of file diff --git a/visualisations/JsRoot460/scripts/JSRootPainter.jquery.js b/visualisations/JsRoot460/scripts/JSRootPainter.jquery.js new file mode 100644 index 0000000..c0282ef --- /dev/null +++ b/visualisations/JsRoot460/scripts/JSRootPainter.jquery.js @@ -0,0 +1,1246 @@ +/// @file JSRootPainter.jquery.js +/// Part of JavaScript ROOT graphics, dependent from jQuery functionality + +(function( factory ) { + if ( typeof define === "function" && define.amd ) { + // AMD. Register as an anonymous module. + define( ['jquery', 'jquery-ui', 'd3', 'JSRootPainter'], factory ); + } else { + + if (typeof jQuery == 'undefined') + throw new Error('jQuery not defined', 'JSRootPainter.jquery.js'); + + if (typeof jQuery.ui == 'undefined') + throw new Error('jQuery-ui not defined','JSRootPainter.jquery.js'); + + if (typeof d3 != 'object') + throw new Error('This extension requires d3.v3.js', 'JSRootPainter.jquery.js'); + + if (typeof JSROOT == 'undefined') + throw new Error('JSROOT is not defined', 'JSRootPainter.jquery.js'); + + if (typeof JSROOT.Painter != 'object') + throw new Error('JSROOT.Painter not defined', 'JSRootPainter.jquery.js'); + + // Browser globals + factory(jQuery, jQuery.ui, d3, JSROOT); + } +} (function($, myui, d3, JSROOT) { + + if ( typeof define === "function" && define.amd ) + JSROOT.loadScript('$$$style/jquery-ui.css'); + + JSROOT.Painter.createMenu = function(maincallback, menuname) { + if (!menuname || (typeof menuname !== 'string')) menuname = 'root_ctx_menu'; + + var menu = { element: null, code: "", cnt: 1, funcs: {}, separ: false }; + + menu.add = function(name, arg, func) { + if (name == "separator") { this.code += "
  • -
  • "; this.separ = true; return; } + + if (name.indexOf("header:")==0) { + this.code += "
  • "+name.substr(7)+"
  • "; + return; + } + + if (name=="endsub:") { this.code += ""; return; } + var close_tag = "", style = "padding-top:2px;padding-bottom:1px"; + if (name.indexOf("sub:")==0) { name = name.substr(4); close_tag="
      "; style += ";padding-right:2em"} + + if (typeof arg == 'function') { func = arg; arg = name; } + + // if ((arg==null) || (typeof arg != 'string')) arg = name; + + if (name.indexOf("chk:")==0) { name = "" + name.substr(4); } else + if (name.indexOf("unk:")==0) { name = "" + name.substr(4); } + + // special handling of first versions with menu support + if (($.ui.version.indexOf("1.10")==0) || ($.ui.version.indexOf("1.9")==0)) + name = '' + name + ''; + + this.code += "
    • " + name + close_tag; + if (typeof func == 'function') this.funcs[this.cnt] = func; // keep call-back function + + this.cnt++; + } + + menu.addchk = function(flag, name, arg, func) { + return this.add((flag ? "chk:" : "unk:") + name, arg, func); + } + + menu.size = function() { return this.cnt-1; } + + menu.addDrawMenu = function(menu_name, opts, call_back) { + if (opts==null) opts = new Array; + if (opts.length==0) opts.push(""); + + this.add((opts.length > 1) ? ("sub:" + menu_name) : menu_name, opts[0], call_back); + if (opts.length<2) return; + + for (var i=0;i' + this.code + '
    '); + + this.element = $('.jsroot_ctxmenu'); + + var pthis = this; + + this.element + .attr('id', menuname) + .css('left', event.clientX + window.pageXOffset) + .css('top', event.clientY + window.pageYOffset) + .css('font-size', '80%') + .css('position', 'absolute') // this overrides ui-menu-items class property + .menu({ + items: "> :not(.ui-widget-header)", + select: function( event, ui ) { + var arg = ui.item.attr('arg'); + var cnt = ui.item.attr('cnt'); + var func = cnt ? pthis.funcs[cnt] : null; + pthis.remove(); + if (typeof func == 'function') { + if ('painter' in menu) + func.bind(pthis.painter)(arg); // if 'painter' field set, returned as this to callback + else + func(arg); + } + } + }); + + var newx = null, newy = null; + + if (event.clientX + this.element.width() > $(window).width()) newx = $(window).width() - this.element.width() - 20; + if (event.clientY + this.element.height() > $(window).height()) newy = $(window).height() - this.element.height() - 20; + + if (newx!==null) this.element.css('left', (newx>0 ? newx : 0) + window.pageXOffset); + if (newy!==null) this.element.css('top', (newy>0 ? newy : 0) + window.pageYOffset); + } + + JSROOT.CallBack(maincallback, menu); + + return menu; + } + + JSROOT.HierarchyPainter.prototype.isLastSibling = function(hitem) { + if (!hitem || !hitem._parent || !hitem._parent._childs) return false; + var chlds = hitem._parent._childs; + var indx = chlds.indexOf(hitem); + if (indx<0) return false; + while (++indx < chlds.length) + if (!('_hidden' in chlds[indx])) return false; + return true; + } + + JSROOT.HierarchyPainter.prototype.addItemHtml = function(hitem, d3prnt, doupdate) { + var isroot = !('_parent' in hitem); + var has_childs = '_childs' in hitem; + + if ('_hidden' in hitem) return; + + var handle = JSROOT.getDrawHandle(hitem._kind), + img1 = "", img2 = "", can_click = false; + + if (handle !== null) { + if ('icon' in handle) img1 = handle.icon; + if ('icon2' in handle) img2 = handle.icon2; + if (('func' in handle) || ('execute' in handle) || ('aslink' in handle) || + (('expand' in handle) && (hitem._more !== false))) can_click = true; + } + + if ('_icon' in hitem) img1 = hitem._icon; + if ('_icon2' in hitem) img2 = hitem._icon2; + if ((img1.length==0) && ('_online' in hitem)) + hitem._icon = img1 = "img_globe"; + if ((img1.length==0) && isroot) + hitem._icon = img1 = "img_base"; + + if (hitem._more || ('_expand' in hitem) || ('_player' in hitem)) + can_click = true; + + var can_menu = can_click; + if (!can_menu && (typeof hitem._kind == 'string') && (hitem._kind.indexOf("ROOT.")==0)) { + can_menu = true; + can_click = true; + } + + if (img2.length==0) img2 = img1; + if (img1.length==0) img1 = (has_childs || hitem._more) ? "img_folder" : "img_page"; + if (img2.length==0) img2 = (has_childs || hitem._more) ? "img_folderopen" : "img_page"; + + var itemname = this.itemFullName(hitem); + + var d3cont; + + if (doupdate) { + d3prnt.selectAll("*").remove(); + d3cont = d3prnt; + } else { + d3cont = d3prnt.append("div"); + } + + hitem._d3cont = d3cont.node(); // set for direct referencing + d3cont.attr("item", itemname); + + // line with all html elements for this item (excluding childs) + var d3line = d3cont.append("div").attr('class','h_line'); + + // build indent + var prnt = isroot ? null : hitem._parent; + while (prnt && (prnt !== this.h)) { + d3line.insert("div",":first-child") + .attr("class", this.isLastSibling(prnt) ? "img_empty" : "img_line"); + prnt = prnt._parent; + } + + var icon_class = "", plusminus = false; + + if (isroot) { + // for root node no extra code + } else + if (has_childs) { + icon_class = hitem._isopen ? "img_minus" : "img_plus"; + plusminus = true; + } else + /*if (hitem._more) { + icon_class = "img_plus"; // should be special plus ??? + plusminus = true; + } else */ { + icon_class = "img_join"; + } + + var h = this; + + if (icon_class.length > 0) { + if (this.isLastSibling(hitem)) icon_class+="bottom"; + var d3icon = d3line.append("div").attr('class', icon_class); + if (plusminus) d3icon.style('cursor','pointer') + .on("click", function() { h.tree_click(this, "plusminus"); }); + } + + // make node icons + + if (this.with_icons) { + var icon_name = hitem._isopen ? img2 : img1; + + var d3img; + + if (icon_name.indexOf("img_")==0) + d3img = d3line.append("div") + .attr("class", icon_name) + .attr("title", hitem._kind); + else + d3img = d3line.append("img") + .attr("src", icon_name) + .attr("alt","") + .attr("title", hitem._kind) + .style('vertical-align','top') + .style('width','18px') + .style('height','18px'); + + if ('_icon_click' in hitem) + d3img.on("click", function() { h.tree_click(this, "icon"); }); + } + + var d3a = d3line.append("a"); + if (can_click || has_childs) + d3a.attr("class","h_item") + .on("click", function() { h.tree_click(this); }); + + if ('disp_kind' in h) { + if (JSROOT.gStyle.DragAndDrop && can_click) + this.enable_dragging(d3a.node(), itemname); + if (JSROOT.gStyle.ContextMenu && can_menu) + d3a.on('contextmenu', function() { h.tree_contextmenu(this); }); + } + + var element_name = hitem._name; + + if ('_realname' in hitem) + element_name = hitem._realname; + + var element_title = ""; + if ('_title' in hitem) element_title = hitem._title; + + if ('_fullname' in hitem) + element_title += " fullname: " + hitem._fullname; + + if (element_title.length === 0) + element_title = element_name; + + d3a.attr('title', element_title) + .text(element_name + ('_value' in hitem ? ":" : "")) + .style('background', hitem._background ? hitem._background : null); + + if ('_value' in hitem) { + var d3p = d3line.append("p"); + if ('_vclass' in hitem) d3p.attr('class', hitem._vclass); + if (!hitem._isopen) d3p.html(hitem._value); + } + + if (has_childs && (isroot || hitem._isopen)) { + var d3chlds = d3cont.append("div").attr("class", "h_childs"); + for (var i=0; i< hitem._childs.length;++i) { + var chld = hitem._childs[i]; + chld._parent = hitem; + this.addItemHtml(chld, d3chlds); + } + } + } + + JSROOT.HierarchyPainter.prototype.RefreshHtml = function(callback) { + + if (this.divid == null) return JSROOT.CallBack(callback); + var d3elem = this.select_main(); + + d3elem.html(""); // clear html - most simple way + + var h = this, factcmds = [], status_item = null; + this.ForEach(function(item) { + delete item._d3cont; // remove html container + if (('_fastcmd' in item) && (item._kind == 'Command')) factcmds.push(item); + if (('_status' in item) && (status_item==null)) status_item = item; + }); + + if ((this.h == null) || d3elem.empty()) + return JSROOT.CallBack(callback); + + + var maindiv = + d3elem.append("div") + .attr("class", "jsroot") + .style("background-color", this.background ? this.background : "") +// .style('overflow', 'auto') +// .style('width', '100%') +// .style('height', '100%') + .style('font-size', this.with_icons ? "12px" : "15px"); + + for (var n=0;nx'; + return el.firstChild.href; + } + + JSROOT.Painter.createMenu(function(menu) { + + menu.painter = painter; + + if ((itemname == "") && !('_jsonfile' in hitem)) { + var addr = "", cnt = 0; + function separ() { return cnt++ > 0 ? "&" : "?"; } + + var files = []; + painter.ForEachRootFile(function(item) { files.push(item._file.fFullURL); }); + + if (painter.GetTopOnlineItem()==null) + addr = JSROOT.source_dir + "index.htm"; + + if (painter.IsMonitoring()) + addr += separ() + "monitoring=" + painter.MonitoringInterval(); + + if (files.length==1) + addr += separ() + "file=" + files[0]; + else + if (files.length>1) + addr += separ() + "files=" + JSON.stringify(files); + + if (painter['disp_kind']) + addr += separ() + "layout=" + painter.disp_kind.replace(/ /g, ""); + + var items = []; + + if (painter.disp) + painter.disp.ForEachPainter(function(p) { + if (p.GetItemName()!=null) + items.push(p.GetItemName()); + }); + + if (items.length == 1) { + addr += separ() + "item=" + items[0]; + } else if (items.length > 1) { + addr += separ() + "items=" + JSON.stringify(items); + } + + menu.add("Direct link", function() { window.open(addr); }); + menu.add("Only items", function() { window.open(addr + "&nobrowser"); }); + } else + if (onlineprop != null) { + painter.FillOnlineMenu(menu, onlineprop, itemname); + } else { + var opts = JSROOT.getDrawOptions(hitem._kind, 'nosame'); + + if (opts) + menu.addDrawMenu("Draw", opts, function(arg) { this.display(itemname, arg); }); + + if (fileprop && opts) { + var filepath = qualifyURL(fileprop.fileurl); + if (filepath.indexOf(JSROOT.source_dir) == 0) + filepath = filepath.slice(JSROOT.source_dir.length); + filepath = fileprop.kind + "=" + filepath; + if (fileprop.itemname.length > 0) { + var name = fileprop.itemname; + if (name.search(/\+| |\,/)>=0) name = "\'" + name + "\'"; + filepath += "&item=" + name; + } + + menu.addDrawMenu("Draw in new tab", opts, function(arg) { + window.open(JSROOT.source_dir + "index.htm?nobrowser&"+filepath +"&opt="+arg); + }); + } + + if (!('_childs' in hitem) && (hitem._more || !('_more' in hitem))) + menu.add("Expand", function() { painter.expand(itemname); }); + } + + if (typeof hitem._menu == 'function') + hitem._menu(menu, hitem, painter); + + if (menu.size() > 0) { + menu.tree_node = elem.parentNode; + if (menu.separ) menu.add("separator"); // add separator at the end + menu.add("Close"); + menu.show(d3.event); + } + + }); // end menu creation + + return false; + } + + JSROOT.HierarchyPainter.prototype.CreateDisplay = function(callback) { + if ('disp' in this) { + if (this.disp.NumDraw() > 0) return JSROOT.CallBack(callback, this.disp); + this.disp.Reset(); + delete this.disp; + } + + // check that we can found frame where drawing should be done + if (document.getElementById(this.disp_frameid) == null) + return JSROOT.CallBack(callback, null); + + if (this.disp_kind == "tabs") + this.disp = new JSROOT.TabsDisplay(this.disp_frameid); + else + if ((this.disp_kind == "flex") || (this.disp_kind == "flexible")) + this.disp = new JSROOT.FlexibleDisplay(this.disp_frameid); + else + if (this.disp_kind.search("grid") == 0) + this.disp = new JSROOT.GridDisplay(this.disp_frameid, this.disp_kind); + else + if (this.disp_kind == "simple") + this.disp = new JSROOT.SimpleDisplay(this.disp_frameid); + else + this.disp = new JSROOT.CollapsibleDisplay(this.disp_frameid); + + JSROOT.CallBack(callback, this.disp); + } + + JSROOT.HierarchyPainter.prototype.enable_dragging = function(element, itemname) { + $(element).draggable({ revert: "invalid", appendTo: "body", helper: "clone" }); + } + + JSROOT.HierarchyPainter.prototype.enable_dropping = function(frame, itemname) { + var h = this; + $(frame).droppable({ + hoverClass : "ui-state-active", + accept: function(ui) { + var dropname = ui.parent().parent().attr('item'); + if ((dropname == itemname) || (dropname==null)) return false; + + var ditem = h.Find(dropname); + if ((ditem==null) || (!('_kind' in ditem))) return false; + + return ditem._kind.indexOf("ROOT.")==0; + }, + drop: function(event, ui) { + var dropname = ui.draggable.parent().parent().attr('item'); + if (dropname==null) return false; + return h.dropitem(dropname, $(this).attr("id")); + } + }); + } + + // ================================================== + + JSROOT.CollapsibleDisplay = function(frameid) { + JSROOT.MDIDisplay.call(this, frameid); + this.cnt = 0; // use to count newly created frames + } + + JSROOT.CollapsibleDisplay.prototype = Object.create(JSROOT.MDIDisplay.prototype); + + JSROOT.CollapsibleDisplay.prototype.ForEachFrame = function(userfunc, only_visible) { + var topid = this.frameid + '_collapsible'; + + if (document.getElementById(topid) == null) return; + + if (typeof userfunc != 'function') return; + + $('#' + topid + ' .collapsible_draw').each(function() { + + // check if only visible specified + if (only_visible && $(this).is(":hidden")) return; + + userfunc($(this).get(0)); + }); + } + + JSROOT.CollapsibleDisplay.prototype.ActivateFrame = function(frame) { + if ($(frame).is(":hidden")) { + $(frame).prev().toggleClass("ui-accordion-header-active ui-state-active ui-state-default ui-corner-bottom") + .find("> .ui-icon").toggleClass("ui-icon-triangle-1-e ui-icon-triangle-1-s").end() + .next().toggleClass("ui-accordion-content-active").slideDown(0); + } + $(frame).prev()[0].scrollIntoView(); + } + + JSROOT.CollapsibleDisplay.prototype.CreateFrame = function(title) { + + var topid = this.frameid + '_collapsible'; + + if (document.getElementById(topid) == null) + $("#"+this.frameid).append('
    '); + + var hid = topid + "_sub" + this.cnt++; + var uid = hid + "h"; + + var entryInfo = "
    " + + "" + + " " + title + "  " + + "
    \n"; + entryInfo += "
    \n"; + $("#" + topid).append(entryInfo); + + $('#' + uid) + .addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-top ui-corner-bottom") + .hover(function() { $(this).toggleClass("ui-state-hover"); }) + .click( function() { + $(this).toggleClass("ui-accordion-header-active ui-state-active ui-state-default ui-corner-bottom") + .find("> .ui-icon").toggleClass("ui-icon-triangle-1-e ui-icon-triangle-1-s") + .end().next().toggleClass("ui-accordion-content-active").slideToggle(0); + JSROOT.resize($(this).next().attr('id')); + return false; + }) + .next() + .addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom") + .hide(); + + $('#' + uid).find(" .jsroot_collaps_closebtn") + .button({ icons: { primary: "ui-icon-close" }, text: false }) + .click(function(){ + JSROOT.cleanup($(this).parent().next().attr('id')); + $(this).parent().next().andSelf().remove(); + }); + + $('#' + uid) + .toggleClass("ui-accordion-header-active ui-state-active ui-state-default ui-corner-bottom") + .find("> .ui-icon").toggleClass("ui-icon-triangle-1-e ui-icon-triangle-1-s").end().next() + .toggleClass("ui-accordion-content-active").slideToggle(0); + + return $("#" + hid).attr('frame_title', title).css('overflow','hidden').get(0); + } + + // ================================================ + + JSROOT.TabsDisplay = function(frameid) { + JSROOT.MDIDisplay.call(this, frameid); + this.cnt = 0; + } + + JSROOT.TabsDisplay.prototype = Object.create(JSROOT.MDIDisplay.prototype); + + JSROOT.TabsDisplay.prototype.ForEachFrame = function(userfunc, only_visible) { + var topid = this.frameid + '_tabs'; + + if (document.getElementById(topid) == null) return; + + if (typeof userfunc != 'function') return; + + var cnt = -1; + var active = $('#' + topid).tabs("option", "active"); + + $('#' + topid + '> .tabs_draw').each(function() { + cnt++; + if (!only_visible || (cnt == active)) + userfunc($(this).get(0)); + }); + } + + JSROOT.TabsDisplay.prototype.ActivateFrame = function(frame) { + var cnt = 0, id = -1; + this.ForEachFrame(function(fr) { + if ($(fr).attr('id') == $(frame).attr('id')) id = cnt; + cnt++; + }); + $('#' + this.frameid + "_tabs").tabs("option", "active", id); + } + + JSROOT.TabsDisplay.prototype.CreateFrame = function(title) { + var topid = this.frameid + '_tabs'; + + var hid = topid + "_sub" + this.cnt++; + + var li = '
  • ' + title + + 'Remove Tab
  • '; + var cont = '
    '; + + if (document.getElementById(topid) == null) { + $("#" + this.frameid).append('
    ' + '
      ' + li + '
    ' + cont + '
    '); + + var tabs = $("#" + topid) + .css('overflow','hidden') + .tabs({ + heightStyle : "fill", + activate : function (event,ui) { + $(ui.newPanel).css('overflow', 'hidden'); + JSROOT.resize($(ui.newPanel).attr('id')); + } + }); + + tabs.delegate("span.ui-icon-close", "click", function() { + var panelId = $(this).closest("li").remove().attr("aria-controls"); + JSROOT.cleanup(panelId); + $("#" + panelId).remove(); + tabs.tabs("refresh"); + if ($('#' + topid + '> .tabs_draw').length == 0) + $("#" + topid).remove(); + + }); + } else { + $("#" + topid).find("> .ui-tabs-nav").append(li); + $("#" + topid).append(cont); + $("#" + topid).tabs("refresh"); + $("#" + topid).tabs("option", "active", -1); + } + $('#' + hid) + .empty() + .css('overflow', 'hidden') + .attr('frame_title', title); + + return $('#' + hid).get(0); + } + + // ================================================== + + JSROOT.FlexibleDisplay = function(frameid) { + JSROOT.MDIDisplay.call(this, frameid); + this.cnt = 0; // use to count newly created frames + } + + JSROOT.FlexibleDisplay.prototype = Object.create(JSROOT.MDIDisplay.prototype); + + JSROOT.FlexibleDisplay.prototype.ForEachFrame = function(userfunc, only_visible) { + var topid = this.frameid + '_flex'; + + if (document.getElementById(topid) == null) return; + if (typeof userfunc != 'function') return; + + $('#' + topid + ' .flex_draw').each(function() { + // check if only visible specified + //if (only_visible && $(this).is(":hidden")) return; + + userfunc($(this).get(0)); + }); + } + + JSROOT.FlexibleDisplay.prototype.ActivateFrame = function(frame) { + } + + JSROOT.FlexibleDisplay.prototype.CreateFrame = function(title) { + var topid = this.frameid + '_flex'; + + if (document.getElementById(topid) == null) + $("#" + this.frameid).append('
    '); + + var top = $("#" + topid); + + var w = top.width(), h = top.height(); + + var subid = topid + "_frame" + this.cnt; + + var entry ='
    ' + + '
    '+ + '

    '+title+'

    ' + + '
    ' + + '
    ' + + '
    '; + + top.append(entry); + + function ChangeWindowState(main, state) { + var curr = main.prop('state'); + if (!curr) curr = "normal"; + main.prop('state', state); + if (state==curr) return; + + if (curr == "normal") { + main.prop('original_height', main.height()); + main.prop('original_width', main.width()); + main.prop('original_top', main.css('top')); + main.prop('original_left', main.css('left')); + } + + main.find(".jsroot_minbutton").find('.ui-icon') + .toggleClass("ui-icon-carat-1-s", state!="minimal") + .toggleClass("ui-icon-carat-2-n-s", state=="minimal"); + + main.find(".jsroot_maxbutton").find('.ui-icon') + .toggleClass("ui-icon-carat-1-n", state!="maximal") + .toggleClass("ui-icon-carat-2-n-s", state=="maximal"); + + switch (state) { + case "minimal" : + main.height(main.find('.flex_header').height()).width("auto"); + main.find(".flex_draw").css("display","none"); + main.find(".ui-resizable-handle").css("display","none"); + break; + case "maximal" : + main.height("100%").width("100%").css('left','').css('top',''); + main.find(".flex_draw").css("display",""); + main.find(".ui-resizable-handle").css("display","none"); + break; + default: + main.find(".flex_draw").css("display",""); + main.find(".ui-resizable-handle").css("display",""); + main.height(main.prop('original_height')) + .width(main.prop('original_width')); + if (curr!="minimal") + main.css('left', main.prop('original_left')) + .css('top', main.prop('original_top')); + } + + if (state !== "minimal") + JSROOT.resize(main.find(".flex_draw").get(0)); + } + + $("#" + subid) + .css('left', parseInt(w * (this.cnt % 5)/10)) + .css('top', parseInt(h * (this.cnt % 5)/10)) + .width(Math.round(w * 0.58)) + .height(Math.round(h * 0.58)) + .resizable({ + helper: "jsroot-flex-resizable-helper", + start: function(event, ui) { + // bring element to front when start resizing + $(this).appendTo($(this).parent()); + }, + stop: function(event, ui) { + var rect = { width : ui.size.width-1, height : ui.size.height - $(this).find(".flex_header").height()-1 }; + JSROOT.resize($(this).find(".flex_draw").get(0), rect); + } + }) + .draggable({ + containment: "parent", + start: function(event, ui) { + // bring element to front when start dragging + $(this).appendTo($(this).parent()); + var ddd = $(this).find(".flex_draw"); + + if (ddd.prop('flex_block_drag') === true) { + // block dragging when mouse below header + var elementMouseIsOver = document.elementFromPoint(event.clientX, event.clientY); + var isparent = false; + $(elementMouseIsOver).parents().map(function() { if ($(this).get(0) === ddd.get(0)) isparent = true; }); + if (isparent) return false; + } + } + }) + .find('.flex_header') + // .hover(function() { $(this).toggleClass("ui-state-hover"); }) + .click(function() { + var div = $(this).parent(); + div.appendTo(div.parent()); + }) + .find("button") + .first() + .attr('title','close canvas') + .button({ icons: { primary: "ui-icon-close" }, text: false }) + .click(function() { + var main = $(this).parent().parent(); + JSROOT.cleanup(main.find(".flex_draw").get(0)); + main.remove(); + }) + .next() + .attr('title','maximize canvas') + .addClass('jsroot_maxbutton') + .button({ icons: { primary: "ui-icon-carat-1-n" }, text: false }) + .click(function() { + var main = $(this).parent().parent(); + var maximize = $(this).find('.ui-icon').hasClass("ui-icon-carat-1-n"); + ChangeWindowState(main, maximize ? "maximal" : "normal"); + }) + .next() + .attr('title','minimize canvas') + .addClass('jsroot_minbutton') + .button({ icons: { primary: "ui-icon-carat-1-s" }, text: false }) + .click(function() { + var main = $(this).parent().parent(); + var minimize = $(this).find('.ui-icon').hasClass("ui-icon-carat-1-s"); + ChangeWindowState(main, minimize ? "minimal" : "normal"); + }); + + // set default z-index to avoid overlap of these special elements + $("#" + subid).find(".ui-resizable-handle").css('z-index', ''); + + //var draw_w = $("#" + subid).width() - 1; + //var draw_h = $("#" + subid).height() - $("#" + subid).find(".flex_header").height()-1; + //$("#" + subid).find(".flex_draw").width(draw_w).height(draw_h); + this.cnt++; + + return $("#" + subid + "_cont").attr('frame_title', title).get(0); + } + + // ========== performs tree drawing on server ================== + + JSROOT.TTreePlayer = function(itemname, url, askey, root_version) { + JSROOT.TBasePainter.call(this); + this.SetItemName(itemname); + this.url = url; + this.root_version = root_version; + this.hist_painter = null; + this.askey = askey; + return this; + } + + JSROOT.TTreePlayer.prototype = Object.create( JSROOT.TBasePainter.prototype ); + + JSROOT.TTreePlayer.prototype.Show = function(divid) { + this.drawid = divid + "_draw"; + + $("#" + divid) + .html("
    " + + "" + + " Expr: " + + "" + + "
    " + + "
    "); + + var player = this; + + $("#" + divid).find('.treedraw_exe').click(function() { player.PerformDraw(); }); + $("#" + divid).find('.treedraw_varexp') + .val("px:py") + .keyup(function(e){ + if(e.keyCode == 13) player.PerformDraw(); + }); + + $("#" + divid).find('.treedraw_more').click(function() { + $(this).remove(); + $("#" + divid).find(".treedraw_buttons") + .append(" Cut:"+ + " Opt:"+ + " Num:" + + " First:"); + + $("#" + divid +" .treedraw_opt").val(""); + $("#" + divid +" .treedraw_number").val("").spinner({ numberFormat: "n", min: 0, page: 1000}); + $("#" + divid +" .treedraw_first").val("").spinner({ numberFormat: "n", min: 0, page: 1000}); + }); + + this.SetDivId(divid); + + this.CheckResize(); + } + + JSROOT.TTreePlayer.prototype.PerformDraw = function() { + + var frame = $(this.select_main().node()); + + var url = this.url + '/exe.json.gz?compact=3&method=Draw'; + var expr = frame.find('.treedraw_varexp').val(); + var hname = "h_tree_draw"; + + var pos = expr.indexOf(">>"); + if (pos<0) { + expr += ">>" + hname; + } else { + hname = expr.substr(pos+2); + if (hname[0]=='+') hname = hname.substr(1); + var pos2 = hname.indexOf("("); + if (pos2>0) hname = hname.substr(0, pos2); + } + + if (frame.find('.treedraw_more').length==0) { + var cut = frame.find('.treedraw_cut').val(); + var option = frame.find('.treedraw_opt').val(); + var nentries = frame.find('.treedraw_number').val(); + var firstentry = frame.find('.treedraw_first').val(); + + url += '&prototype="const char*,const char*,Option_t*,Long64_t,Long64_t"&varexp="' + expr + '"&selection="' + cut + '"'; + + // if any of optional arguments specified, specify all of them + if ((option!="") || (nentries!="") || (firstentry!="")) { + if (nentries=="") nentries = (this.root_version >= 394499) ? "TTree::kMaxEntries": "1000000000"; // kMaxEntries available since ROOT 6.05/03 + if (firstentry=="") firstentry = "0"; + url += '&option="' + option + '"&nentries=' + nentries + '&firstentry=' + firstentry; + } + } else { + url += '&prototype="Option_t*"&opt="' + expr + '"'; + } + url += '&_ret_object_=' + hname; + + var player = this; + + function SubmitDrawRequest() { + JSROOT.NewHttpRequest(url, 'object', function(res) { + if (res==null) return; + $("#"+player.drawid).empty(); + player.hist_painter = JSROOT.draw(player.drawid, res) + }).send(); + } + + if (this.askey) { + // first let read tree from the file + this.askey = false; + JSROOT.NewHttpRequest(this.url + "/root.json", 'text', SubmitDrawRequest).send(); + } else SubmitDrawRequest(); + } + + JSROOT.TTreePlayer.prototype.CheckResize = function(arg) { + var main = $(this.select_main().node()); + + $("#" + this.drawid).width(main.width()); + var h = main.height(); + var h0 = main.find(".treedraw_buttons").height(); + $("#" + this.drawid).height(h - 1 - h0); + + if (this.hist_painter) + this.hist_painter.CheckResize(arg); + } + + JSROOT.drawTreePlayer = function(hpainter, itemname, askey) { + + var url = hpainter.GetOnlineItemUrl(itemname); + if (url == null) return null; + + var top = hpainter.GetTopOnlineItem(hpainter.Find(itemname)); + if (top == null) return null; + var root_version = ('_root_version' in top) ? top._root_version : 336417; // by default use version number 5-34-32 + + var mdi = hpainter.GetDisplay(); + if (mdi == null) return null; + + var frame = mdi.FindFrame(itemname, true); + if (frame==null) return null; + + var divid = d3.select(frame).attr('id'); + + var player = new JSROOT.TTreePlayer(itemname, url, askey, root_version); + player.Show(divid); + return player; + } + + JSROOT.drawTreePlayerKey = function(hpainter, itemname) { + // function used when tree is not yet loaded on the server + + return JSROOT.drawTreePlayer(hpainter, itemname, true); + } + + + // ======================================================================= + + JSROOT.Painter.separ = null; + + JSROOT.Painter.AdjustLayout = function(left, height, firsttime) { + if (this.separ == null) return; + + if (left!=null) { + var wdiff = $("#"+this.separ.left).outerWidth() - $("#"+this.separ.left).width(); + var w = 5; + $("#"+this.separ.vertical).css('left', left + "px").width(w).css('top','1px'); + $("#"+this.separ.left).width(left-wdiff-1).css('top','1px'); + $("#"+this.separ.right).css('left',left+w+"px").css('top','1px'); + if (!this.separ.horizontal) { + $("#"+this.separ.vertical).css('bottom', '1px'); + $("#"+this.separ.left).css('bottom', '1px'); + $("#"+this.separ.right).css('bottom', '1px'); + } + } + + if ((height!=null) && this.separ.horizontal) { + var diff = $("#"+this.separ.bottom).outerHeight() - $("#"+this.separ.bottom).height(); + height -= 2*diff; + if (height<5) height = 5; + var bot = height + diff; + $('#'+this.separ.bottom).height(height); + var h = 5; + $("#"+this.separ.horizontal).css('bottom', bot + 'px').height(h); + bot += h; + $("#"+this.separ.left).css('bottom', bot + 'px'); + } + + if (this.separ.horizontal) + if (this.separ.hpart) { + var ww = $("#"+this.separ.left).outerWidth() - 2; + $('#'+this.separ.bottom).width(ww); + $("#"+this.separ.horizontal).width(ww); + } else { + var bot = $("#"+this.separ.left).css('bottom'); + $("#"+this.separ.vertical).css('bottom', bot); + $("#"+this.separ.right).css('bottom', bot); + } + + if (firsttime || (this.separ.handle==null)) return; + + if (typeof this.separ.handle == 'function') this.separ.handle(); else + if ((typeof this.separ.handle == 'object') && + (typeof this.separ.handle.CheckResize === 'function')) this.separ.handle.CheckResize(); + } + + JSROOT.Painter.ConfigureVSeparator = function(handle) { + + JSROOT.Painter.separ = { handle: handle, left: "left-div", right: "right-div", vertical: "separator-div", + horizontal : null, bottom : null, hpart: true }; + + $("#separator-div").addClass("separator").draggable({ + axis: "x" , zIndex: 100, cursor: "ew-resize", + helper : function() { return $("#separator-div").clone().attr('id','separator-clone').css('background-color','grey'); }, + stop: function(event,ui) { + event.stopPropagation(); + var left = ui.position.left; + $("#separator-clone").remove(); + JSROOT.Painter.AdjustLayout(left, null, false); + } + }); + + var w0 = Math.round($(window).width() * 0.2); + if (w0<300) w0 = Math.min(300, Math.round($(window).width() * 0.5)); + + JSROOT.Painter.AdjustLayout(w0, null, true); + } + + JSROOT.Painter.ConfigureHSeparator = function(height, onlyleft) { + + if ((JSROOT.Painter.separ == null) || + (JSROOT.Painter.separ.horizontal != null)) return null; + + JSROOT.Painter.separ['horizontal'] = 'horizontal-separator-div'; + JSROOT.Painter.separ['bottom'] = 'bottom-div'; + JSROOT.Painter.separ.hpart = (onlyleft === true); + + var prnt = $("#"+this.separ.left).parent(); + + prnt.append('
    '); + prnt.append('
    '); + + $("#horizontal-separator-div").addClass("separator").draggable({ + axis: "y" , zIndex: 100, cursor: "ns-resize", + helper : function() { return $("#horizontal-separator-div").clone().attr('id','horizontal-separator-clone').css('background-color','grey'); }, + stop: function(event,ui) { + event.stopPropagation(); + var top = $(window).height() - ui.position.top; + $('#horizontal-separator-clone').remove(); + JSROOT.Painter.AdjustLayout(null, top, false); + } + }); + + JSROOT.Painter.AdjustLayout(null, height, false); + + return JSROOT.Painter.separ.bottom; + } + + return JSROOT.Painter; + +})); + diff --git a/visualisations/JsRoot460/scripts/JSRootPainter.jquery.min.js b/visualisations/JsRoot460/scripts/JSRootPainter.jquery.min.js new file mode 100644 index 0000000..d5f43ef --- /dev/null +++ b/visualisations/JsRoot460/scripts/JSRootPainter.jquery.min.js @@ -0,0 +1 @@ +(function(a){if(typeof define==="function"&&define.amd){define(["jquery","jquery-ui","d3","JSRootPainter"],a)}else{if(typeof jQuery=="undefined"){throw new Error("jQuery not defined","JSRootPainter.jquery.js")}if(typeof jQuery.ui=="undefined"){throw new Error("jQuery-ui not defined","JSRootPainter.jquery.js")}if(typeof d3!="object"){throw new Error("This extension requires d3.v3.js","JSRootPainter.jquery.js")}if(typeof JSROOT=="undefined"){throw new Error("JSROOT is not defined","JSRootPainter.jquery.js")}if(typeof JSROOT.Painter!="object"){throw new Error("JSROOT.Painter not defined","JSRootPainter.jquery.js")}a(jQuery,jQuery.ui,d3,JSROOT)}}(function(c,d,b,a){if(typeof define==="function"&&define.amd){a.loadScript("$$$style/jquery-ui.css")}a.Painter.createMenu=function(e,f){if(!f||(typeof f!=="string")){f="root_ctx_menu"}var g={element:null,code:"",cnt:1,funcs:{},separ:false};g.add=function(i,h,l){if(i=="separator"){this.code+="
  • -
  • ";this.separ=true;return}if(i.indexOf("header:")==0){this.code+="
  • "+i.substr(7)+"
  • ";return}if(i=="endsub:"){this.code+="";return}var k="",j="padding-top:2px;padding-bottom:1px";if(i.indexOf("sub:")==0){i=i.substr(4);k="
      ";j+=";padding-right:2em"}if(typeof h=="function"){l=h;h=i}if(i.indexOf("chk:")==0){i=""+i.substr(4)}else{if(i.indexOf("unk:")==0){i=""+i.substr(4)}}if((c.ui.version.indexOf("1.10")==0)||(c.ui.version.indexOf("1.9")==0)){i=''+i+""}this.code+="
    • "+i+k;if(typeof l=="function"){this.funcs[this.cnt]=l}this.cnt++};g.addchk=function(i,j,h,k){return this.add((i?"chk:":"unk:")+j,h,k)};g.size=function(){return this.cnt-1};g.addDrawMenu=function(m,k,l){if(k==null){k=new Array}if(k.length==0){k.push("")}this.add((k.length>1)?("sub:"+m):m,k[0],l);if(k.length<2){return}for(var j=0;j'+this.code+"
    ");this.element=c(".jsroot_ctxmenu");var h=this;this.element.attr("id",f).css("left",j.clientX+window.pageXOffset).css("top",j.clientY+window.pageYOffset).css("font-size","80%").css("position","absolute").menu({items:"> :not(.ui-widget-header)",select:function(q,r){var n=r.item.attr("arg");var o=r.item.attr("cnt");var p=o?h.funcs[o]:null;h.remove();if(typeof p=="function"){if("painter" in g){p.bind(h.painter)(n)}else{p(n)}}}});var m=null,k=null;if(j.clientX+this.element.width()>c(window).width()){m=c(window).width()-this.element.width()-20}if(j.clientY+this.element.height()>c(window).height()){k=c(window).height()-this.element.height()-20}if(m!==null){this.element.css("left",(m>0?m:0)+window.pageXOffset)}if(k!==null){this.element.css("top",(k>0?k:0)+window.pageYOffset)}};a.CallBack(e,g);return g};a.HierarchyPainter.prototype.isLastSibling=function(f){if(!f||!f._parent||!f._parent._childs){return false}var e=f._parent._childs;var g=e.indexOf(f);if(g<0){return false}while(++g0){if(this.isLastSibling(e)){f+="bottom"}var p=g.append("div").attr("class",f);if(n){p.style("cursor","pointer").on("click",function(){y.tree_click(this,"plusminus")})}}if(this.with_icons){var A=e._isopen?F:G;var l;if(A.indexOf("img_")==0){l=g.append("div").attr("class",A).attr("title",e._kind)}else{l=g.append("img").attr("src",A).attr("alt","").attr("title",e._kind).style("vertical-align","top").style("width","18px").style("height","18px")}if("_icon_click" in e){l.on("click",function(){y.tree_click(this,"icon")})}}var s=g.append("a");if(v||j){s.attr("class","h_item").on("click",function(){y.tree_click(this)})}if("disp_kind" in y){if(a.gStyle.DragAndDrop&&v){this.enable_dragging(s.node(),q)}if(a.gStyle.ContextMenu&&B){s.on("contextmenu",function(){y.tree_contextmenu(this)})}}var r=e._name;if("_realname" in e){r=e._realname}var t="";if("_title" in e){t=e._title}if("_fullname" in e){t+=" fullname: "+e._fullname}if(t.length===0){t=r}s.attr("title",t).text(r+("_value" in e?":":"")).style("background",e._background?e._background:null);if("_value" in e){var k=g.append("p");if("_vclass" in e){k.attr("class",e._vclass)}if(!e._isopen){k.html(e._value)}}if(j&&(o||e._isopen)){var E=z.append("div").attr("class","h_childs");for(var x=0;xx';return m.firstChild.href}a.Painter.createMenu(function(o){o.painter=e;if((k=="")&&!("_jsonfile" in f)){var s="",p=0;function q(){return p++>0?"&":"?"}var n=[];e.ForEachRootFile(function(u){n.push(u._file.fFullURL)});if(e.GetTopOnlineItem()==null){s=a.source_dir+"index.htm"}if(e.IsMonitoring()){s+=q()+"monitoring="+e.MonitoringInterval()}if(n.length==1){s+=q()+"file="+n[0]}else{if(n.length>1){s+=q()+"files="+JSON.stringify(n)}}if(e.disp_kind){s+=q()+"layout="+e.disp_kind.replace(/ /g,"")}var r=[];if(e.disp){e.disp.ForEachPainter(function(u){if(u.GetItemName()!=null){r.push(u.GetItemName())}})}if(r.length==1){s+=q()+"item="+r[0]}else{if(r.length>1){s+=q()+"items="+JSON.stringify(r)}}o.add("Direct link",function(){window.open(s)});o.add("Only items",function(){window.open(s+"&nobrowser")})}else{if(j!=null){e.FillOnlineMenu(o,j,k)}else{var l=a.getDrawOptions(f._kind,"nosame");if(l){o.addDrawMenu("Draw",l,function(u){this.display(k,u)})}if(i&&l){var t=h(i.fileurl);if(t.indexOf(a.source_dir)==0){t=t.slice(a.source_dir.length)}t=i.kind+"="+t;if(i.itemname.length>0){var m=i.itemname;if(m.search(/\+| |\,/)>=0){m="'"+m+"'"}t+="&item="+m}o.addDrawMenu("Draw in new tab",l,function(u){window.open(a.source_dir+"index.htm?nobrowser&"+t+"&opt="+u)})}if(!("_childs" in f)&&(f._more||!("_more" in f))){o.add("Expand",function(){e.expand(k)})}}}if(typeof f._menu=="function"){f._menu(o,f,e)}if(o.size()>0){o.tree_node=g.parentNode;if(o.separ){o.add("separator")}o.add("Close");o.show(b.event)}});return false};a.HierarchyPainter.prototype.CreateDisplay=function(e){if("disp" in this){if(this.disp.NumDraw()>0){return a.CallBack(e,this.disp)}this.disp.Reset();delete this.disp}if(document.getElementById(this.disp_frameid)==null){return a.CallBack(e,null)}if(this.disp_kind=="tabs"){this.disp=new a.TabsDisplay(this.disp_frameid)}else{if((this.disp_kind=="flex")||(this.disp_kind=="flexible")){this.disp=new a.FlexibleDisplay(this.disp_frameid)}else{if(this.disp_kind.search("grid")==0){this.disp=new a.GridDisplay(this.disp_frameid,this.disp_kind)}else{if(this.disp_kind=="simple"){this.disp=new a.SimpleDisplay(this.disp_frameid)}else{this.disp=new a.CollapsibleDisplay(this.disp_frameid)}}}}a.CallBack(e,this.disp)};a.HierarchyPainter.prototype.enable_dragging=function(e,f){c(e).draggable({revert:"invalid",appendTo:"body",helper:"clone"})};a.HierarchyPainter.prototype.enable_dropping=function(f,g){var e=this;c(f).droppable({hoverClass:"ui-state-active",accept:function(j){var i=j.parent().parent().attr("item");if((i==g)||(i==null)){return false}var h=e.Find(i);if((h==null)||(!("_kind" in h))){return false}return h._kind.indexOf("ROOT.")==0},drop:function(i,j){var h=j.draggable.parent().parent().attr("item");if(h==null){return false}return e.dropitem(h,c(this).attr("id"))}})};a.CollapsibleDisplay=function(e){a.MDIDisplay.call(this,e);this.cnt=0};a.CollapsibleDisplay.prototype=Object.create(a.MDIDisplay.prototype);a.CollapsibleDisplay.prototype.ForEachFrame=function(f,g){var e=this.frameid+"_collapsible";if(document.getElementById(e)==null){return}if(typeof f!="function"){return}c("#"+e+" .collapsible_draw").each(function(){if(g&&c(this).is(":hidden")){return}f(c(this).get(0))})};a.CollapsibleDisplay.prototype.ActivateFrame=function(e){if(c(e).is(":hidden")){c(e).prev().toggleClass("ui-accordion-header-active ui-state-active ui-state-default ui-corner-bottom").find("> .ui-icon").toggleClass("ui-icon-triangle-1-e ui-icon-triangle-1-s").end().next().toggleClass("ui-accordion-content-active").slideDown(0)}c(e).prev()[0].scrollIntoView()};a.CollapsibleDisplay.prototype.CreateFrame=function(i){var g=this.frameid+"_collapsible";if(document.getElementById(g)==null){c("#"+this.frameid).append('
    ')}var f=g+"_sub"+this.cnt++;var h=f+"h";var e='
    "+i+" 
    \n";e+="
    \n";c("#"+g).append(e);c("#"+h).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-top ui-corner-bottom").hover(function(){c(this).toggleClass("ui-state-hover")}).click(function(){c(this).toggleClass("ui-accordion-header-active ui-state-active ui-state-default ui-corner-bottom").find("> .ui-icon").toggleClass("ui-icon-triangle-1-e ui-icon-triangle-1-s").end().next().toggleClass("ui-accordion-content-active").slideToggle(0);a.resize(c(this).next().attr("id"));return false}).next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom").hide();c("#"+h).find(" .jsroot_collaps_closebtn").button({icons:{primary:"ui-icon-close"},text:false}).click(function(){a.cleanup(c(this).parent().next().attr("id"));c(this).parent().next().andSelf().remove()});c("#"+h).toggleClass("ui-accordion-header-active ui-state-active ui-state-default ui-corner-bottom").find("> .ui-icon").toggleClass("ui-icon-triangle-1-e ui-icon-triangle-1-s").end().next().toggleClass("ui-accordion-content-active").slideToggle(0);return c("#"+f).attr("frame_title",i).css("overflow","hidden").get(0)};a.TabsDisplay=function(e){a.MDIDisplay.call(this,e);this.cnt=0};a.TabsDisplay.prototype=Object.create(a.MDIDisplay.prototype);a.TabsDisplay.prototype.ForEachFrame=function(f,i){var e=this.frameid+"_tabs";if(document.getElementById(e)==null){return}if(typeof f!="function"){return}var g=-1;var h=c("#"+e).tabs("option","active");c("#"+e+"> .tabs_draw").each(function(){g++;if(!i||(g==h)){f(c(this).get(0))}})};a.TabsDisplay.prototype.ActivateFrame=function(f){var e=0,g=-1;this.ForEachFrame(function(h){if(c(h).attr("id")==c(f).attr("id")){g=e}e++});c("#"+this.frameid+"_tabs").tabs("option","active",g)};a.TabsDisplay.prototype.CreateFrame=function(j){var h=this.frameid+"_tabs";var g=h+"_sub"+this.cnt++;var f='
  • '+j+'Remove Tab
  • ';var e='
    ';if(document.getElementById(h)==null){c("#"+this.frameid).append('
      '+f+"
    "+e+"
    ");var i=c("#"+h).css("overflow","hidden").tabs({heightStyle:"fill",activate:function(k,l){c(l.newPanel).css("overflow","hidden");a.resize(c(l.newPanel).attr("id"))}});i.delegate("span.ui-icon-close","click",function(){var k=c(this).closest("li").remove().attr("aria-controls");a.cleanup(k);c("#"+k).remove();i.tabs("refresh");if(c("#"+h+"> .tabs_draw").length==0){c("#"+h).remove()}})}else{c("#"+h).find("> .ui-tabs-nav").append(f);c("#"+h).append(e);c("#"+h).tabs("refresh");c("#"+h).tabs("option","active",-1)}c("#"+g).empty().css("overflow","hidden").attr("frame_title",j);return c("#"+g).get(0)};a.FlexibleDisplay=function(e){a.MDIDisplay.call(this,e);this.cnt=0};a.FlexibleDisplay.prototype=Object.create(a.MDIDisplay.prototype);a.FlexibleDisplay.prototype.ForEachFrame=function(f,g){var e=this.frameid+"_flex";if(document.getElementById(e)==null){return}if(typeof f!="function"){return}c("#"+e+" .flex_draw").each(function(){f(c(this).get(0))})};a.FlexibleDisplay.prototype.ActivateFrame=function(e){};a.FlexibleDisplay.prototype.CreateFrame=function(m){var g=this.frameid+"_flex";if(document.getElementById(g)==null){c("#"+this.frameid).append('
    ')}var k=c("#"+g);var f=k.width(),i=k.height();var e=g+"_frame"+this.cnt;var j='

    '+m+'

    ';k.append(j);function l(h,n){var o=h.prop("state");if(!o){o="normal"}h.prop("state",n);if(n==o){return}if(o=="normal"){h.prop("original_height",h.height());h.prop("original_width",h.width());h.prop("original_top",h.css("top"));h.prop("original_left",h.css("left"))}h.find(".jsroot_minbutton").find(".ui-icon").toggleClass("ui-icon-carat-1-s",n!="minimal").toggleClass("ui-icon-carat-2-n-s",n=="minimal");h.find(".jsroot_maxbutton").find(".ui-icon").toggleClass("ui-icon-carat-1-n",n!="maximal").toggleClass("ui-icon-carat-2-n-s",n=="maximal");switch(n){case"minimal":h.height(h.find(".flex_header").height()).width("auto");h.find(".flex_draw").css("display","none");h.find(".ui-resizable-handle").css("display","none");break;case"maximal":h.height("100%").width("100%").css("left","").css("top","");h.find(".flex_draw").css("display","");h.find(".ui-resizable-handle").css("display","none");break;default:h.find(".flex_draw").css("display","");h.find(".ui-resizable-handle").css("display","");h.height(h.prop("original_height")).width(h.prop("original_width"));if(o!="minimal"){h.css("left",h.prop("original_left")).css("top",h.prop("original_top"))}}if(n!=="minimal"){a.resize(h.find(".flex_draw").get(0))}}c("#"+e).css("left",parseInt(f*(this.cnt%5)/10)).css("top",parseInt(i*(this.cnt%5)/10)).width(Math.round(f*0.58)).height(Math.round(i*0.58)).resizable({helper:"jsroot-flex-resizable-helper",start:function(h,n){c(this).appendTo(c(this).parent())},stop:function(n,o){var h={width:o.size.width-1,height:o.size.height-c(this).find(".flex_header").height()-1};a.resize(c(this).find(".flex_draw").get(0),h)}}).draggable({containment:"parent",start:function(n,p){c(this).appendTo(c(this).parent());var o=c(this).find(".flex_draw");if(o.prop("flex_block_drag")===true){var q=document.elementFromPoint(n.clientX,n.clientY);var h=false;c(q).parents().map(function(){if(c(this).get(0)===o.get(0)){h=true}});if(h){return false}}}}).find(".flex_header").click(function(){var h=c(this).parent();h.appendTo(h.parent())}).find("button").first().attr("title","close canvas").button({icons:{primary:"ui-icon-close"},text:false}).click(function(){var h=c(this).parent().parent();a.cleanup(h.find(".flex_draw").get(0));h.remove()}).next().attr("title","maximize canvas").addClass("jsroot_maxbutton").button({icons:{primary:"ui-icon-carat-1-n"},text:false}).click(function(){var h=c(this).parent().parent();var n=c(this).find(".ui-icon").hasClass("ui-icon-carat-1-n");l(h,n?"maximal":"normal")}).next().attr("title","minimize canvas").addClass("jsroot_minbutton").button({icons:{primary:"ui-icon-carat-1-s"},text:false}).click(function(){var h=c(this).parent().parent();var n=c(this).find(".ui-icon").hasClass("ui-icon-carat-1-s");l(h,n?"minimal":"normal")});c("#"+e).find(".ui-resizable-handle").css("z-index","");this.cnt++;return c("#"+e+"_cont").attr("frame_title",m).get(0)};a.TTreePlayer=function(h,f,g,e){a.TBasePainter.call(this);this.SetItemName(h);this.url=f;this.root_version=e;this.hist_painter=null;this.askey=g;return this};a.TTreePlayer.prototype=Object.create(a.TBasePainter.prototype);a.TTreePlayer.prototype.Show=function(f){this.drawid=f+"_draw";c("#"+f).html("
    Expr:
    ");var e=this;c("#"+f).find(".treedraw_exe").click(function(){e.PerformDraw()});c("#"+f).find(".treedraw_varexp").val("px:py").keyup(function(g){if(g.keyCode==13){e.PerformDraw()}});c("#"+f).find(".treedraw_more").click(function(){c(this).remove();c("#"+f).find(".treedraw_buttons").append(" Cut: Opt: Num: First:");c("#"+f+" .treedraw_opt").val("");c("#"+f+" .treedraw_number").val("").spinner({numberFormat:"n",min:0,page:1000});c("#"+f+" .treedraw_first").val("").spinner({numberFormat:"n",min:0,page:1000})});this.SetDivId(f);this.CheckResize()};a.TTreePlayer.prototype.PerformDraw=function(){var g=c(this.select_main().node());var f=this.url+"/exe.json.gz?compact=3&method=Draw";var o=g.find(".treedraw_varexp").val();var e="h_tree_draw";var l=o.indexOf(">>");if(l<0){o+=">>"+e}else{e=o.substr(l+2);if(e[0]=="+"){e=e.substr(1)}var m=e.indexOf("(");if(m>0){e=e.substr(0,m)}}if(g.find(".treedraw_more").length==0){var n=g.find(".treedraw_cut").val();var h=g.find(".treedraw_opt").val();var k=g.find(".treedraw_number").val();var j=g.find(".treedraw_first").val();f+='&prototype="const char*,const char*,Option_t*,Long64_t,Long64_t"&varexp="'+o+'"&selection="'+n+'"';if((h!="")||(k!="")||(j!="")){if(k==""){k=(this.root_version>=394499)?"TTree::kMaxEntries":"1000000000"}if(j==""){j="0"}f+='&option="'+h+'"&nentries='+k+"&firstentry="+j}}else{f+='&prototype="Option_t*"&opt="'+o+'"'}f+="&_ret_object_="+e;var p=this;function i(){a.NewHttpRequest(f,"object",function(q){if(q==null){return}c("#"+p.drawid).empty();p.hist_painter=a.draw(p.drawid,q)}).send()}if(this.askey){this.askey=false;a.NewHttpRequest(this.url+"/root.json","text",i).send()}else{i()}};a.TTreePlayer.prototype.CheckResize=function(f){var e=c(this.select_main().node());c("#"+this.drawid).width(e.width());var i=e.height();var g=e.find(".treedraw_buttons").height();c("#"+this.drawid).height(i-1-g);if(this.hist_painter){this.hist_painter.CheckResize(f)}};a.drawTreePlayer=function(h,k,j){var e=h.GetOnlineItemUrl(k);if(e==null){return null}var m=h.GetTopOnlineItem(h.Find(k));if(m==null){return null}var f=("_root_version" in m)?m._root_version:336417;var i=h.GetDisplay();if(i==null){return null}var g=i.FindFrame(k,true);if(g==null){return null}var l=b.select(g).attr("id");var n=new a.TTreePlayer(k,e,j,f);n.Show(l);return n};a.drawTreePlayerKey=function(e,f){return a.drawTreePlayer(e,f,true)};a.Painter.separ=null;a.Painter.AdjustLayout=function(e,n,k){if(this.separ==null){return}if(e!=null){var g=c("#"+this.separ.left).outerWidth()-c("#"+this.separ.left).width();var m=5;c("#"+this.separ.vertical).css("left",e+"px").width(m).css("top","1px");c("#"+this.separ.left).width(e-g-1).css("top","1px");c("#"+this.separ.right).css("left",e+m+"px").css("top","1px");if(!this.separ.horizontal){c("#"+this.separ.vertical).css("bottom","1px");c("#"+this.separ.left).css("bottom","1px");c("#"+this.separ.right).css("bottom","1px")}}if((n!=null)&&this.separ.horizontal){var l=c("#"+this.separ.bottom).outerHeight()-c("#"+this.separ.bottom).height();n-=2*l;if(n<5){n=5}var j=n+l;c("#"+this.separ.bottom).height(n);var i=5;c("#"+this.separ.horizontal).css("bottom",j+"px").height(i);j+=i;c("#"+this.separ.left).css("bottom",j+"px")}if(this.separ.horizontal){if(this.separ.hpart){var f=c("#"+this.separ.left).outerWidth()-2;c("#"+this.separ.bottom).width(f);c("#"+this.separ.horizontal).width(f)}else{var j=c("#"+this.separ.left).css("bottom");c("#"+this.separ.vertical).css("bottom",j);c("#"+this.separ.right).css("bottom",j)}}if(k||(this.separ.handle==null)){return}if(typeof this.separ.handle=="function"){this.separ.handle()}else{if((typeof this.separ.handle=="object")&&(typeof this.separ.handle.CheckResize==="function")){this.separ.handle.CheckResize()}}};a.Painter.ConfigureVSeparator=function(f){a.Painter.separ={handle:f,left:"left-div",right:"right-div",vertical:"separator-div",horizontal:null,bottom:null,hpart:true};c("#separator-div").addClass("separator").draggable({axis:"x",zIndex:100,cursor:"ew-resize",helper:function(){return c("#separator-div").clone().attr("id","separator-clone").css("background-color","grey")},stop:function(g,h){g.stopPropagation();var i=h.position.left;c("#separator-clone").remove();a.Painter.AdjustLayout(i,null,false)}});var e=Math.round(c(window).width()*0.2);if(e<300){e=Math.min(300,Math.round(c(window).width()*0.5))}a.Painter.AdjustLayout(e,null,true)};a.Painter.ConfigureHSeparator=function(e,g){if((a.Painter.separ==null)||(a.Painter.separ.horizontal!=null)){return null}a.Painter.separ.horizontal="horizontal-separator-div";a.Painter.separ.bottom="bottom-div";a.Painter.separ.hpart=(g===true);var f=c("#"+this.separ.left).parent();f.append('
    ');f.append('
    ');c("#horizontal-separator-div").addClass("separator").draggable({axis:"y",zIndex:100,cursor:"ns-resize",helper:function(){return c("#horizontal-separator-div").clone().attr("id","horizontal-separator-clone").css("background-color","grey")},stop:function(h,i){h.stopPropagation();var j=c(window).height()-i.position.top;c("#horizontal-separator-clone").remove();a.Painter.AdjustLayout(null,j,false)}});a.Painter.AdjustLayout(null,e,false);return a.Painter.separ.bottom};return a.Painter})); \ No newline at end of file diff --git a/visualisations/JsRoot460/scripts/JSRootPainter.js b/visualisations/JsRoot460/scripts/JSRootPainter.js new file mode 100644 index 0000000..ba2da7f --- /dev/null +++ b/visualisations/JsRoot460/scripts/JSRootPainter.js @@ -0,0 +1,10158 @@ +/// @file JSRootPainter.js +/// JavaScript ROOT graphics + +(function( factory ) { + if ( typeof define === "function" && define.amd ) { + // AMD. Register as an anonymous module. + define( ['JSRootCore', 'd3'], factory ); + } else { + + if (typeof JSROOT == 'undefined') + throw new Error('JSROOT is not defined', 'JSRootPainter.js'); + + if (typeof d3 != 'object') + throw new Error('d3 is not defined', 'JSRootPainter.js'); + + if (typeof JSROOT.Painter == 'object') + throw new Error('JSROOT.Painter already defined', 'JSRootPainter.js'); + + factory(JSROOT, d3); + } +} (function(JSROOT, d3) { + + // do it here while require.js does not provide method to load css files + if ( typeof define === "function" && define.amd ) + JSROOT.loadScript('$$$style/JSRootPainter.css'); + + // list of user painters, called with arguments func(vis, obj, opt) + JSROOT.DrawFuncs = {lst:[], cache:{}}; + + // add draw function for the class + // List of supported draw options could be provided, separated with ';' + // Several different draw functions for the same class or kind could be specified + JSROOT.addDrawFunc = function(_name, _func, _opt) { + if ((arguments.length == 1) && (typeof arguments[0] == 'object')) { + JSROOT.DrawFuncs.lst.push(arguments[0]); + return arguments[0]; + } + var handle = { name:_name, func:_func, opt:_opt }; + JSROOT.DrawFuncs.lst.push(handle); + return handle; + } + + // icons taken from http://uxrepo.com/ + + JSROOT.ToolbarIcons = { + camera: { path: 'M 152.00,304.00c0.00,57.438, 46.562,104.00, 104.00,104.00s 104.00-46.562, 104.00-104.00s-46.562-104.00-104.00-104.00S 152.00,246.562, 152.00,304.00z M 480.00,128.00L 368.00,128.00 c-8.00-32.00-16.00-64.00-48.00-64.00L 192.00,64.00 c-32.00,0.00-40.00,32.00-48.00,64.00L 32.00,128.00 c-17.60,0.00-32.00,14.40-32.00,32.00l0.00,288.00 c0.00,17.60, 14.40,32.00, 32.00,32.00l 448.00,0.00 c 17.60,0.00, 32.00-14.40, 32.00-32.00L 512.00,160.00 C 512.00,142.40, 497.60,128.00, 480.00,128.00z M 256.00,446.00c-78.425,0.00-142.00-63.574-142.00-142.00c0.00-78.425, 63.575-142.00, 142.00-142.00c 78.426,0.00, 142.00,63.575, 142.00,142.00 C 398.00,382.426, 334.427,446.00, 256.00,446.00z M 480.00,224.00l-64.00,0.00 l0.00-32.00 l 64.00,0.00 L 480.00,224.00 z' }, + disk: { path: 'M384,0H128H32C14.336,0,0,14.336,0,32v448c0,17.656,14.336,32,32,32h448c17.656,0,32-14.344,32-32V96L416,0H384z M352,160 V32h32v128c0,17.664-14.344,32-32,32H160c-17.664,0-32-14.336-32-32V32h128v128H352z M96,288c0-17.656,14.336-32,32-32h256 c17.656,0,32,14.344,32,32v192H96V288z' }, + question: { path: 'M256,512c141.375,0,256-114.625,256-256S397.375,0,256,0S0,114.625,0,256S114.625,512,256,512z M256,64 c63.719,0,128,36.484,128,118.016c0,47.453-23.531,84.516-69.891,110.016C300.672,299.422,288,314.047,288,320 c0,17.656-14.344,32-32,32c-17.664,0-32-14.344-32-32c0-40.609,37.25-71.938,59.266-84.031 C315.625,218.109,320,198.656,320,182.016C320,135.008,279.906,128,256,128c-30.812,0-64,20.227-64,64.672 c0,17.664-14.336,32-32,32s-32-14.336-32-32C128,109.086,193.953,64,256,64z M256,449.406c-18.211,0-32.961-14.75-32.961-32.969 c0-18.188,14.75-32.953,32.961-32.953c18.219,0,32.969,14.766,32.969,32.953C288.969,434.656,274.219,449.406,256,449.406z' }, + undo: { path: 'M450.159,48.042c8.791,9.032,16.983,18.898,24.59,29.604c7.594,10.706,14.146,22.207,19.668,34.489 c5.509,12.296,9.82,25.269,12.92,38.938c3.113,13.669,4.663,27.834,4.663,42.499c0,14.256-1.511,28.863-4.532,43.822 c-3.009,14.952-7.997,30.217-14.953,45.795c-6.955,15.577-16.202,31.52-27.755,47.826s-25.88,32.9-42.942,49.807 c-5.51,5.444-11.787,11.67-18.834,18.651c-7.033,6.98-14.496,14.366-22.39,22.168c-7.88,7.802-15.955,15.825-24.187,24.069 c-8.258,8.231-16.333,16.203-24.252,23.888c-18.3,18.13-37.354,37.016-57.191,56.65l-56.84-57.445 c19.596-19.472,38.54-38.279,56.84-56.41c7.75-7.685,15.772-15.604,24.108-23.757s16.438-16.163,24.33-24.057 c7.894-7.893,15.356-15.33,22.402-22.312c7.034-6.98,13.312-13.193,18.821-18.651c22.351-22.402,39.165-44.648,50.471-66.738 c11.279-22.09,16.932-43.567,16.932-64.446c0-15.785-3.217-31.005-9.638-45.671c-6.422-14.665-16.229-28.504-29.437-41.529 c-3.282-3.282-7.358-6.395-12.217-9.325c-4.871-2.938-10.381-5.503-16.516-7.697c-6.121-2.201-12.815-3.992-20.058-5.373 c-7.242-1.374-14.9-2.064-23.002-2.064c-8.218,0-16.802,0.834-25.788,2.507c-8.961,1.674-18.053,4.429-27.222,8.271 c-9.189,3.842-18.456,8.869-27.808,15.089c-9.358,6.219-18.521,13.819-27.502,22.793l-59.92,60.271l93.797,94.058H0V40.91 l93.27,91.597l60.181-60.532c13.376-15.018,27.222-27.248,41.536-36.697c14.308-9.443,28.608-16.776,42.89-21.992 c14.288-5.223,28.505-8.74,42.623-10.557C294.645,0.905,308.189,0,321.162,0c13.429,0,26.389,1.185,38.84,3.562 c12.478,2.377,24.2,5.718,35.192,10.029c11.006,4.311,21.126,9.404,30.374,15.265C434.79,34.724,442.995,41.119,450.159,48.042z' }, + arrow_right : { path : 'M30.796,226.318h377.533L294.938,339.682c-11.899,11.906-11.899,31.184,0,43.084c11.887,11.899,31.19,11.893,43.077,0 l165.393-165.386c5.725-5.712,8.924-13.453,8.924-21.539c0-8.092-3.213-15.84-8.924-21.551L338.016,8.925 C332.065,2.975,324.278,0,316.478,0c-7.802,0-15.603,2.968-21.539,8.918c-11.899,11.906-11.899,31.184,0,43.084l113.391,113.384 H30.796c-16.822,0-30.463,13.645-30.463,30.463C0.333,212.674,13.974,226.318,30.796,226.318z' }, + arrow_up : { path : 'M295.505,629.446V135.957l148.193,148.206c15.555,15.559,40.753,15.559,56.308,0c15.555-15.538,15.546-40.767,0-56.304 L283.83,11.662C276.372,4.204,266.236,0,255.68,0c-10.568,0-20.705,4.204-28.172,11.662L11.333,227.859 c-7.777,7.777-11.666,17.965-11.666,28.158c0,10.192,3.88,20.385,11.657,28.158c15.563,15.555,40.762,15.555,56.317,0 l148.201-148.219v493.489c0,21.993,17.837,39.82,39.82,39.82C277.669,669.267,295.505,651.439,295.505,629.446z' }, + arrow_diag : { path : 'M279.875,511.994c-1.292,0-2.607-0.102-3.924-0.312c-10.944-1.771-19.333-10.676-20.457-21.71L233.97,278.348 L22.345,256.823c-11.029-1.119-19.928-9.51-21.698-20.461c-1.776-10.944,4.031-21.716,14.145-26.262L477.792,2.149 c9.282-4.163,20.167-2.165,27.355,5.024c7.201,7.189,9.199,18.086,5.024,27.356L302.22,497.527 C298.224,506.426,289.397,511.994,279.875,511.994z M118.277,217.332l140.534,14.294c11.567,1.178,20.718,10.335,21.878,21.896 l14.294,140.519l144.09-320.792L118.277,217.332z' }, + auto_zoom: { path : 'M505.441,242.47l-78.303-78.291c-9.18-9.177-24.048-9.171-33.216,0c-9.169,9.172-9.169,24.045,0.006,33.217l38.193,38.188 H280.088V80.194l38.188,38.199c4.587,4.584,10.596,6.881,16.605,6.881c6.003,0,12.018-2.297,16.605-6.875 c9.174-9.172,9.174-24.039,0.011-33.217L273.219,6.881C268.803,2.471,262.834,0,256.596,0c-6.229,0-12.202,2.471-16.605,6.881 l-78.296,78.302c-9.178,9.172-9.178,24.045,0,33.217c9.177,9.171,24.051,9.171,33.21,0l38.205-38.205v155.4H80.521l38.2-38.188 c9.177-9.171,9.177-24.039,0.005-33.216c-9.171-9.172-24.039-9.178-33.216,0L7.208,242.464c-4.404,4.403-6.881,10.381-6.881,16.611 c0,6.227,2.477,12.207,6.881,16.61l78.302,78.291c4.587,4.581,10.599,6.875,16.605,6.875c6.006,0,12.023-2.294,16.61-6.881 c9.172-9.174,9.172-24.036-0.005-33.211l-38.205-38.199h152.593v152.063l-38.199-38.211c-9.171-9.18-24.039-9.18-33.216-0.022 c-9.178,9.18-9.178,24.059-0.006,33.222l78.284,78.302c4.41,4.404,10.382,6.881,16.611,6.881c6.233,0,12.208-2.477,16.611-6.881 l78.302-78.296c9.181-9.18,9.181-24.048,0-33.205c-9.174-9.174-24.054-9.174-33.21,0l-38.199,38.188v-152.04h152.051l-38.205,38.199 c-9.18,9.175-9.18,24.037-0.005,33.211c4.587,4.587,10.596,6.881,16.604,6.881c6.01,0,12.024-2.294,16.605-6.875l78.303-78.285 c4.403-4.403,6.887-10.378,6.887-16.611C512.328,252.851,509.845,246.873,505.441,242.47z' }, + statbox : { + path : 'M28.782,56.902H483.88c15.707,0,28.451-12.74,28.451-28.451C512.331,12.741,499.599,0,483.885,0H28.782 C13.074,0,0.331,12.741,0.331,28.451C0.331,44.162,13.074,56.902,28.782,56.902z' + + 'M483.885,136.845H28.782c-15.708,0-28.451,12.741-28.451,28.451c0,15.711,12.744,28.451,28.451,28.451H483.88 c15.707,0,28.451-12.74,28.451-28.451C512.331,149.586,499.599,136.845,483.885,136.845z' + + 'M483.885,273.275H28.782c-15.708,0-28.451,12.731-28.451,28.452c0,15.707,12.744,28.451,28.451,28.451H483.88 c15.707,0,28.451-12.744,28.451-28.451C512.337,286.007,499.599,273.275,483.885,273.275z' + + 'M256.065,409.704H30.492c-15.708,0-28.451,12.731-28.451,28.451c0,15.707,12.744,28.451,28.451,28.451h225.585 c15.707,0,28.451-12.744,28.451-28.451C284.516,422.436,271.785,409.704,256.065,409.704z' + } + }; + + JSROOT.Toolbar = function(container, buttons) { + if ((container !== undefined) && (typeof container.append == 'function')) { + this.element = container.append("div").attr('class','jsroot'); + this.addButtons(buttons); + } + } + + JSROOT.Toolbar.prototype.addButtons = function(buttons) { + var pthis = this; + + this.buttonsNames = []; + buttons.forEach(function(buttonGroup) { + var group = pthis.element.append('div').attr('class', 'toolbar-group'); + + buttonGroup.forEach(function(buttonConfig) { + var buttonName = buttonConfig.name; + if (!buttonName) { + throw new Error('must provide button \'name\' in button config'); + } + if (pthis.buttonsNames.indexOf(buttonName) !== -1) { + throw new Error('button name \'' + buttonName + '\' is taken'); + } + pthis.buttonsNames.push(buttonName); + + pthis.createButton(group, buttonConfig); + }); + }); + }; + + + JSROOT.Toolbar.prototype.createButton = function(group, config) { + + var title = config.title; + if (title === undefined) title = config.name; + + if (typeof config.click !== 'function') + throw new Error('must provide button \'click\' function in button config'); + + var button = group.append('a') + .attr('class','toolbar-btn') + .attr('rel', 'tooltip') + .attr('data-title', title) + .on('click', config.click); + + this.createIcon(button, config.icon || JSROOT.ToolbarIcons.question); + }; + + JSROOT.Toolbar.prototype.createIcon = function(button, thisIcon) { + var size = thisIcon.size || 512; + var scale = thisIcon.scale || 1; + + var svg = button.append("svg:svg") + .attr('height', '1em') + .attr('width', '1em') + .attr('viewBox', [0, 0, size, size].join(' ')) + + if ('recs' in thisIcon) { + var rec = {}; + for (var n=0;n0) && (palette<113)) JSROOT.gStyle.Palette = palette; + } + + var embed3d = JSROOT.GetUrlOption("embed3d", url); + if (embed3d !== null) JSROOT.gStyle.Embed3DinSVG = parseInt(embed3d); + + var webgl = JSROOT.GetUrlOption("webgl", url); + if ((webgl === "0") || (webgl === "false")) JSROOT.gStyle.NoWebGL = true; else + if (webgl === "ie") JSROOT.gStyle.NoWebGL = !JSROOT.browser.isIE; + + var geosegm = JSROOT.GetUrlOption("geosegm", url); + if (geosegm!==null) JSROOT.gStyle.GeoGradPerSegm = Math.max(2, parseInt(geosegm)); + var geocomp = JSROOT.GetUrlOption("geocomp", url); + if (geocomp!==null) JSROOT.gStyle.GeoCompressComp = (geocomp!=='0') && (geocomp!=='false'); + } + + JSROOT.Painter.Coord = { + kCARTESIAN : 1, + kPOLAR : 2, + kCYLINDRICAL : 3, + kSPHERICAL : 4, + kRAPIDITY : 5 + } + + /** Function that generates all root colors */ + JSROOT.Painter.root_colors = function() { + var colorMap = ['white','black','red','green','blue','yellow','magenta','cyan','rgb(89,212,84)','rgb(89,84,217)', 'white']; + colorMap[110] = 'white'; + + var moreCol = [ + {col:11,str:'c1b7ad4d4d4d6666668080809a9a9ab3b3b3cdcdcde6e6e6f3f3f3cdc8accdc8acc3c0a9bbb6a4b3a697b8a49cae9a8d9c8f83886657b1cfc885c3a48aa9a1839f8daebdc87b8f9a768a926983976e7b857d9ad280809caca6c0d4cf88dfbb88bd9f83c89a7dc08378cf5f61ac8f94a6787b946971d45a549300ff7b00ff6300ff4b00ff3300ff1b00ff0300ff0014ff002cff0044ff005cff0074ff008cff00a4ff00bcff00d4ff00ecff00fffd00ffe500ffcd00ffb500ff9d00ff8500ff6d00ff5500ff3d00ff2600ff0e0aff0022ff003aff0052ff006aff0082ff009aff00b1ff00c9ff00e1ff00f9ff00ffef00ffd700ffbf00ffa700ff8f00ff7700ff6000ff4800ff3000ff1800ff0000'}, + {col:201,str:'5c5c5c7b7b7bb8b8b8d7d7d78a0f0fb81414ec4848f176760f8a0f14b81448ec4876f1760f0f8a1414b84848ec7676f18a8a0fb8b814ecec48f1f1768a0f8ab814b8ec48ecf176f10f8a8a14b8b848ecec76f1f1'}, + {col:390,str:'ffffcdffff9acdcd9affff66cdcd669a9a66ffff33cdcd339a9a33666633ffff00cdcd009a9a00666600333300'}, + {col:406,str:'cdffcd9aff9a9acd9a66ff6666cd66669a6633ff3333cd33339a3333663300ff0000cd00009a00006600003300'}, + {col:422,str:'cdffff9affff9acdcd66ffff66cdcd669a9a33ffff33cdcd339a9a33666600ffff00cdcd009a9a006666003333'}, + {col:590,str:'cdcdff9a9aff9a9acd6666ff6666cd66669a3333ff3333cd33339a3333660000ff0000cd00009a000066000033'}, + {col:606,str:'ffcdffff9affcd9acdff66ffcd66cd9a669aff33ffcd33cd9a339a663366ff00ffcd00cd9a009a660066330033'}, + {col:622,str:'ffcdcdff9a9acd9a9aff6666cd66669a6666ff3333cd33339a3333663333ff0000cd00009a0000660000330000'}, + {col:791,str:'ffcd9acd9a669a66339a6600cd9a33ffcd66ff9a00ffcd33cd9a00ffcd00ff9a33cd66006633009a3300cd6633ff9a66ff6600ff6633cd3300ff33009aff3366cd00336600339a0066cd339aff6666ff0066ff3333cd0033ff00cdff9a9acd66669a33669a009acd33cdff669aff00cdff339acd00cdff009affcd66cd9a339a66009a6633cd9a66ffcd00ff6633ffcd00cd9a00ffcd33ff9a00cd66006633009a3333cd6666ff9a00ff9a33ff6600cd3300ff339acdff669acd33669a00339a3366cd669aff0066ff3366ff0033cd0033ff339aff0066cd00336600669a339acd66cdff009aff33cdff009acd00cdffcd9aff9a66cd66339a66009a9a33cdcd66ff9a00ffcd33ff9a00cdcd00ff9a33ff6600cd33006633009a6633cd9a66ff6600ff6633ff3300cd3300ffff339acd00666600339a0033cd3366ff669aff0066ff3366cd0033ff0033ff9acdcd669a9a33669a0066cd339aff66cdff009acd009aff33cdff009a'}, + {col:920,str:'cdcdcd9a9a9a666666333333'}]; + + for (var indx = 0; indx < moreCol.length; ++indx) { + var entry = moreCol[indx]; + for (var n=0; n < entry.str.length; n+=6) { + var num = parseInt(entry.col) + parseInt(n/6); + colorMap[num] = 'rgb(' + parseInt("0x" +entry.str.slice(n,n+2)) + "," + parseInt("0x" + entry.str.slice(n+2,n+4)) + "," + parseInt("0x" + entry.str.slice(n+4,n+6)) + ")"; + } + } + + return colorMap; + }(); + + JSROOT.Painter.MakeColorRGB = function(col) { + if ((col==null) || (col._typename != 'TColor')) return null; + var rgb = Math.round(col.fRed*255) + "," + Math.round(col.fGreen*255) + "," + Math.round(col.fBlue*255); + if ((col.fAlpha === undefined) || (col.fAlpha == 1.)) + rgb = "rgb(" + rgb + ")"; + else + rgb = "rgba(" + rgb + "," + col.fAlpha.toFixed(3) + ")"; + + switch (rgb) { + case 'rgb(255,255,255)' : rgb = 'white'; break; + case 'rgb(0,0,0)' : rgb = 'black'; break; + case 'rgb(255,0,0)' : rgb = 'red'; break; + case 'rgb(0,255,0)' : rgb = 'green'; break; + case 'rgb(0,0,255)' : rgb = 'blue'; break; + case 'rgb(255,255,0)' : rgb = 'yellow'; break; + case 'rgb(255,0,255)' : rgb = 'magenta'; break; + case 'rgb(0,255,255)' : rgb = 'cyan'; break; + } + return rgb; + } + + JSROOT.Painter.adoptRootColors = function(objarr) { + if (!objarr || !objarr.arr) return; + + for (var n = 0; n < objarr.arr.length; ++n) { + var col = objarr.arr[n]; + if ((col==null) || (col._typename != 'TColor')) continue; + + var num = col.fNumber; + if ((num<0) || (num>4096)) continue; + + var rgb = JSROOT.Painter.MakeColorRGB(col); + if (rgb == null) continue; + + if (JSROOT.Painter.root_colors[num] != rgb) + JSROOT.Painter.root_colors[num] = rgb; + } + } + + JSROOT.Painter.root_line_styles = new Array("", "", "3,3", "1,2", + "3,4,1,4", "5,3,1,3", "5,3,1,3,1,3,1,3", "5,5", + "5,3,1,3,1,3", "20,5", "20,10,1,10", "1,3"); + + // Initialize ROOT markers + JSROOT.Painter.root_markers = new Array( + 0, 100, 8, 7, 0, // 0..4 + 9, 100, 100, 100, 100, // 5..9 + 100, 100, 100, 100, 100, // 10..14 + 100, 100, 100, 100, 100, // 15..19 + 100, 103, 105, 104, 0, // 20..24 + 3, 4, 2, 1, 106, // 25..29 + 6, 7, 5, 102, 101); // 30..34 + + /** Function returns the ready to use marker for drawing */ + JSROOT.Painter.createAttMarker = function(attmarker, style) { + + var marker_color = JSROOT.Painter.root_colors[attmarker.fMarkerColor]; + + if ((style===null) || (style===undefined)) style = attmarker.fMarkerStyle; + + var res = { x0: 0, y0: 0, color: marker_color, style: style, size: 8, stroke: true, fill: true, marker: "", ndig: 0, used: true, changed: false }; + + res.Change = function(color, style, size) { + + this.changed = true; + + if (color!==undefined) this.color = color; + if (style!==undefined) this.style = style; + if (size!==undefined) this.size = size; else size = this.size; + + this.x0 = this.y0 = 0; + + this.reset_pos = function() { + this.lastx = this.lasty = null; + } + + if ((this.style === 1) || (this.style === 777)) { + this.fill = false; + this.marker = "h1"; + this.size = 1; + + // use special create function to handle relative position movements + this.create = function(x,y) { + var xx = Math.round(x), yy = Math.round(y), m1 = "M"+xx+","+yy+"h1"; + var m2 = (this.lastx===null) ? m1 : ("m"+(xx-this.lastx)+","+(yy-this.lasty)+"h1"); + this.lastx = xx+1; this.lasty = yy; + return (m2.length < m1.length) ? m2 : m1; + } + + this.reset_pos(); + return true; + } + + var marker_kind = ((this.style>0) && (this.style=100); + + switch(this.style) { + case 1: size = this.size = 1; break; + case 6: size = this.size = 2; break; + case 7: size = this.size = 3; break; + default: this.size = size; size*=8; + } + + this.ndig = (size>7) ? 0 : ((size>2) ? 1 : 2); + if (shape == 6) this.ndig++; + var half = (size/2).toFixed(this.ndig), full = size.toFixed(this.ndig); + + switch(shape) { + case 0: // circle + this.x0 = -size/2; + this.marker = "a"+half+","+half+" 0 1,0 "+full+",0a"+half+","+half+" 0 1,0 -"+full+",0z"; + break; + case 1: // cross + var d = (size/3).toFixed(res.ndig); + this.x0 = this.y0 = size/6; + this.marker = "h"+d+"v-"+d+"h-"+d+"v-"+d+"h-"+d+"v"+d+"h-"+d+"v"+d+"h"+d+"v"+d+"h"+d+"z"; + break; + case 2: // diamond + this.x0 = -size/2; + this.marker = "l"+half+",-"+half+"l"+half+","+half+"l-"+half+","+half + "z"; + break; + case 3: // square + this.x0 = this.y0 = -size/2; + this.marker = "v"+full+"h"+full+"v-"+full+"z"; + break; + case 4: // triangle-up + this.y0 = size/2; + this.marker = "l-"+ half+",-"+full+"h"+full+"z"; + break; + case 5: // triangle-down + this.y0 = -size/2; + this.marker = "l-"+ half+","+full+"h"+full+"z"; + break; + case 6: // star + this.y0 = -size/2; + this.marker = "l" + (size/3).toFixed(res.ndig)+","+full + + "l-"+ (5/6*size).toFixed(res.ndig) + ",-" + (5/8*size).toFixed(res.ndig) + + "h" + full + + "l-" + (5/6*size).toFixed(res.ndig) + "," + (5/8*size).toFixed(res.ndig) + "z"; + break; + case 7: // asterisk + this.x0 = this.y0 = -size/2; + this.marker = "l"+full+","+full + + "m0,-"+full+"l-"+full+","+full+ + "m0,-"+half+"h"+full+"m-"+half+",-"+half+"v"+full; + break; + case 8: // plus + this.y0 = -size/2; + this.marker = "v"+full+"m-"+half+",-"+half+"h"+full; + break; + case 9: // mult + this.x0 = this.y0 = -size/2; + this.marker = "l"+full+","+full + "m0,-"+full+"l-"+full+","+full; + break; + default: // diamand + this.x0 = -size/2; + this.marker = "l"+half+",-"+half+"l"+half+","+half+"l-"+half+","+half + "z"; + break; + } + + this.create = function(x,y) { + return "M" + (x+this.x0).toFixed(this.ndig)+ "," + (y+this.y0).toFixed(this.ndig) + this.marker; + } + + return true; + } + + res.Apply = function(selection) { + selection.style('stroke', this.stroke ? this.color : "none"); + selection.style('fill', this.fill ? this.color : "none"); + } + + res.func = res.Apply.bind(res); + + res.Change(marker_color, style, attmarker.fMarkerSize); + + res.changed = false; + + return res; + } + + JSROOT.Painter.createAttLine = function(attline, borderw, can_excl) { + + var color = 0, _width = 0, style = 0; + if (typeof attline == 'string') { + if (attline=='black') { color = 1; _width = 1; } else + if (attline=='none') { _width = 0; } + } else + if (typeof attline == 'object') { + if ('fLineColor' in attline) color = attline.fLineColor; + if ('fLineWidth' in attline) _width = attline.fLineWidth; + if ('fLineStyle' in attline) style = attline.fLineStyle; + } else + if ((attline!==undefined) && !isNaN(attline)) { + color = attline; + } + + if (borderw!==undefined) _width = borderw; + + var line = { + used: true, // can mark object if it used or not, + color: JSROOT.Painter.root_colors[color], + width: _width, + dash: JSROOT.Painter.root_line_styles[style] + }; + + if ((_width==0) || (color==0)) line.color = 'none'; + + if (can_excl) { + line.excl_side = 0; + line.excl_width = 0; + if (Math.abs(line.width) > 99) { + // exclusion graph + line.excl_side = (line.width < 0) ? -1 : 1; + line.excl_width = Math.floor(line.width / 100) * 5; + line.width = line.width % 100; // line width + } + + line.ChangeExcl = function(side,width) { + if (width !== undefined) this.excl_width = width; + if (side !== undefined) { + this.excl_side = side; + if ((this.excl_width===0) && (this.excl_side!==0)) this.excl_width = 20; + } + this.changed = true; + } + } + + // if custom color number used, use lightgrey color to show lines + if ((line.color === undefined) && (color>0)) + line.color = 'lightgrey'; + + line.Apply = function(selection) { + this.used = true; + if (this.color=='none') { + selection.style('stroke', null); + selection.style('stroke-width', null); + selection.style('stroke-dasharray', null); + } else { + selection.style('stroke', this.color); + selection.style('stroke-width', this.width); + if (this.dash && (this.dash.length>0)) + selection.style('stroke-dasharray', this.dash); + } + } + + line.Change = function(color, width, dash) { + if (color !== undefined) this.color = color; + if (width !== undefined) this.width = width; + if (dash !== undefined) this.dash = dash; + this.changed = true; + } + + line.func = line.Apply.bind(line); + + return line; + } + + JSROOT.Painter.clearCuts = function(chopt) { + /* decode string "chopt" and remove graphical cuts */ + var left = chopt.indexOf('['); + var right = chopt.indexOf(']'); + if ((left>=0) && (right>=0) && (left 0) { + if (fontName.charAt(0)==='b') res.weight = "bold"; else + if (fontName.charAt(0)==='i') res.style = "italic"; else + if (fontName.charAt(0)==='o') res.style = "oblique"; else break; + fontName = fontName.substr(1); + } + + if (fontName == 'Symbol') { + res.weight = null; + res.style = null; + } + + res.name = fontName; + + res.SetFont = function(selection) { + selection.attr("font-family", this.name) + .attr("font-size", this.size) + .attr("xml:space","preserve"); + if (this.weight!=null) + selection.attr("font-weight", this.weight); + if (this.style!=null) + selection.attr("font-style", this.style); + } + + res.asStyle = function(sz) { + return ((sz!=null) ? sz : this.size) + "px " + this.name; + } + + res.stringWidth = function(svg, line) { + /* compute the bounding box of a string by using temporary svg:text */ + var text = svg.append("svg:text") + .attr("xml:space","preserve") + .style("opacity", 0) + .text(line); + this.SetFont(text); + var w = text.node().getBBox().width; + text.remove(); + return w; + } + + res.func = res.SetFont.bind(res); + + return res; + } + + JSROOT.Painter.chooseTimeFormat = function(awidth, ticks) { + if (awidth < .5) return ticks ? "%S.%L" : "%M:%S.%L"; + if (awidth < 30) return ticks ? "%Mm%S" : "%H:%M:%S"; + awidth /= 60; if (awidth < 30) return ticks ? "%Hh%M" : "%d/%m %H:%M"; + awidth /= 60; if (awidth < 12) return ticks ? "%d-%Hh" : "%d/%m/%y %Hh"; + awidth /= 24; if (awidth < 15.218425) return ticks ? "%d/%m" : "%d/%m/%y"; + awidth /= 30.43685; if (awidth < 6) return "%d/%m/%y"; + awidth /= 12; if (awidth < 2) return ticks ? "%m/%y" : "%d/%m/%y"; + return "%Y"; + } + + JSROOT.Painter.getTimeFormat = function(axis) { + var idF = axis.fTimeFormat.indexOf('%F'); + if (idF >= 0) return axis.fTimeFormat.substr(0, idF); + return axis.fTimeFormat; + } + + JSROOT.Painter.getTimeOffset = function(axis) { + var idF = axis.fTimeFormat.indexOf('%F'); + if (idF < 0) return JSROOT.gStyle.TimeOffset; + var sof = axis.fTimeFormat.substr(idF + 2); + if (sof == '1995-01-01 00:00:00s0') return 788918400000; + // special case, used from DABC painters + if ((sof == "0") || (sof == "")) return 0; + + // decode time from ROOT string + var dt = new Date(0); + var pos = sof.indexOf("-"); dt.setFullYear(sof.substr(0,pos)); sof = sof.substr(pos+1); + pos = sof.indexOf("-"); dt.setMonth(parseInt(sof.substr(0,pos))-1); sof = sof.substr(pos+1); + pos = sof.indexOf(" "); dt.setDate(sof.substr(0,pos)); sof = sof.substr(pos+1); + pos = sof.indexOf(":"); dt.setHours(sof.substr(0,pos)); sof = sof.substr(pos+1); + pos = sof.indexOf(":"); dt.setMinutes(sof.substr(0,pos)); sof = sof.substr(pos+1); + pos = sof.indexOf("s"); dt.setSeconds(sof.substr(0,pos)); + if (pos>0) { sof = sof.substr(pos+1); dt.setMilliseconds(sof); } + return dt.getTime(); + } + + JSROOT.Painter.formatExp = function(label) { + var str = label; + if (parseFloat(str) == 1.0) return '1'; + if (parseFloat(str) == 10.0) return '10'; + var str = str.replace('e+', 'x10@'); + var str = str.replace('e-', 'x10@-'); + var _val = str.substring(0, str.indexOf('@')); + var _exp = str.substr(str.indexOf('@')); + _val = _val.replace('@', ''); + _exp = _exp.replace('@', ''); + var u, size = _exp.length; + for (var j = 0; j < size; ++j) { + var u, c = _exp.charAt(j); + if (c == '+') u = '\u207A'; else + if (c == '-') u = '\u207B'; else { + var e = parseInt(c); + if (e == 1) u = String.fromCharCode(0xB9); else + if (e > 1 && e < 4) u = String.fromCharCode(0xB0 + e); else + u = String.fromCharCode(0x2070 + e); + } + _exp = _exp.replace(c, u); + } + _val = _val.replace('1x', ''); + return _val + _exp; + }; + + JSROOT.Painter.translateExp = function(str) { + var lstr = str.match(/\^{[0-9]*}/gi); + if (lstr != null) { + var symbol = ''; + for (var i = 0; i < lstr.length; ++i) { + symbol = lstr[i].replace(' ', ''); + symbol = symbol.replace('^{', ''); // &sup + symbol = symbol.replace('}', ''); // ; + var size = symbol.length; + for (var j = 0; j < size; ++j) { + var c = symbol.charAt(j); + var u, e = parseInt(c); + if (e == 1) u = String.fromCharCode(0xB9); + else if (e > 1 && e < 4) u = String.fromCharCode(0xB0 + e); + else u = String.fromCharCode(0x2070 + e); + symbol = symbol.replace(c, u); + } + str = str.replace(lstr[i], symbol); + } + } + return str; + }; + + JSROOT.Painter.symbols_map = { + // greek letters + '#alpha' : '\u03B1', + '#beta' : '\u03B2', + '#chi' : '\u03C7', + '#delta' : '\u03B4', + '#varepsilon' : '\u03B5', + '#phi' : '\u03C6', + '#gamma' : '\u03B3', + '#eta' : '\u03B7', + '#iota' : '\u03B9', + '#varphi' : '\u03C6', + '#kappa' : '\u03BA', + '#lambda' : '\u03BB', + '#mu' : '\u03BC', + '#nu' : '\u03BD', + '#omicron' : '\u03BF', + '#pi' : '\u03C0', + '#theta' : '\u03B8', + '#rho' : '\u03C1', + '#sigma' : '\u03C3', + '#tau' : '\u03C4', + '#upsilon' : '\u03C5', + '#varomega' : '\u03D6', + '#omega' : '\u03C9', + '#xi' : '\u03BE', + '#psi' : '\u03C8', + '#zeta' : '\u03B6', + '#Alpha' : '\u0391', + '#Beta' : '\u0392', + '#Chi' : '\u03A7', + '#Delta' : '\u0394', + '#Epsilon' : '\u0395', + '#Phi' : '\u03A6', + '#Gamma' : '\u0393', + '#Eta' : '\u0397', + '#Iota' : '\u0399', + '#vartheta' : '\u03D1', + '#Kappa' : '\u039A', + '#Lambda' : '\u039B', + '#Mu' : '\u039C', + '#Nu' : '\u039D', + '#Omicron' : '\u039F', + '#Pi' : '\u03A0', + '#Theta' : '\u0398', + '#Rho' : '\u03A1', + '#Sigma' : '\u03A3', + '#Tau' : '\u03A4', + '#Upsilon' : '\u03A5', + '#varsigma' : '\u03C2', + '#Omega' : '\u03A9', + '#Xi' : '\u039E', + '#Psi' : '\u03A8', + '#Zeta' : '\u0396', + '#varUpsilon' : '\u03D2', + '#epsilon' : '\u03B5', + // math symbols + + '#sqrt' : '\u221A', + + // from TLatex tables #2 & #3 + '#leq' : '\u2264', + '#/' : '\u2044', + '#infty' : '\u221E', + '#voidb' : '\u0192', + '#club' : '\u2663', + '#diamond' : '\u2666', + '#heart' : '\u2665', + '#spade' : '\u2660', + '#leftrightarrow' : '\u2194', + '#leftarrow' : '\u2190', + '#uparrow' : '\u2191', + '#rightarrow' : '\u2192', + '#downarrow' : '\u2193', + '#circ' : '\u02C6', // ^ + '#pm' : '\xB1', + '#doublequote' : '\u2033', + '#geq' : '\u2265', + '#times' : '\xD7', + '#propto' : '\u221D', + '#partial' : '\u2202', + '#bullet' : '\u2022', + '#divide' : '\xF7', + '#neq' : '\u2260', + '#equiv' : '\u2261', + '#approx' : '\u2248', // should be \u2245 ? + '#3dots' : '\u2026', + '#cbar' : '\u007C', + '#topbar' : '\xAF', + '#downleftarrow' : '\u21B5', + '#aleph' : '\u2135', + '#Jgothic' : '\u2111', + '#Rgothic' : '\u211C', + '#voidn' : '\u2118', + '#otimes' : '\u2297', + '#oplus' : '\u2295', + '#oslash' : '\u2205', + '#cap' : '\u2229', + '#cup' : '\u222A', + '#supseteq' : '\u2287', + '#supset' : '\u2283', + '#notsubset' : '\u2284', + '#subseteq' : '\u2286', + '#subset' : '\u2282', + '#int' : '\u222B', + '#in' : '\u2208', + '#notin' : '\u2209', + '#angle' : '\u2220', + '#nabla' : '\u2207', + '#oright' : '\xAE', + '#ocopyright' : '\xA9', + '#trademark' : '\u2122', + '#prod' : '\u220F', + '#surd' : '\u221A', + '#upoint' : '\u22C5', + '#corner' : '\xAC', + '#wedge' : '\u2227', + '#vee' : '\u2228', + '#Leftrightarrow' : '\u21D4', + '#Leftarrow' : '\u21D0', + '#Uparrow' : '\u21D1', + '#Rightarrow' : '\u21D2', + '#Downarrow' : '\u21D3', + '#LT' : '\x3C', + '#void1' : '\xAE', + '#copyright' : '\xA9', + '#void3' : '\u2122', + '#sum' : '\u2211', + '#arctop' : '', + '#lbar' : '', + '#arcbottom' : '', + '#void8' : '', + '#bottombar' : '\u230A', + '#arcbar' : '', + '#ltbar' : '', + '#AA' : '\u212B', + '#aa' : '\u00E5', + '#void06' : '', + '#GT' : '\x3E', + '#forall' : '\u2200', + '#exists' : '\u2203', + '#bar' : '', + '#vec' : '', + '#dot' : '\u22C5', + '#hat' : '\xB7', + '#ddot' : '', + '#acute' : '\acute', + '#grave' : '', + '#check' : '\u2713', + '#tilde' : '\u02DC', + '#slash' : '\u2044', + '#hbar' : '\u0127', + '#box' : '', + '#Box' : '', + '#parallel' : '', + '#perp' : '\u22A5', + '#odot' : '', + '#left' : '', + '#right' : '' + }; + + JSROOT.Painter.translateLaTeX = function(string) { + var str = string; + str = this.translateExp(str); + while (str.indexOf('^{o}') != -1) + str = str.replace('^{o}', '\xBA'); + var lstr = str.match(/\#sqrt{(.*?)}/gi); + if (lstr != null) + for (var i = 0; i < lstr.length; ++i) { + var symbol = lstr[i].replace(' ', ''); + symbol = symbol.replace('#sqrt{', '#sqrt'); + symbol = symbol.replace('}', ''); + str = str.replace(lstr[i], symbol); + } + lstr = str.match(/\_{(.*?)}/gi); + if (lstr != null) + for (var i = 0; i < lstr.length; ++i) { + var symbol = lstr[i].replace(' ', ''); + symbol = symbol.replace('_{', ''); // &sub + symbol = symbol.replace('}', ''); // ; + str = str.replace(lstr[i], symbol); + } + lstr = str.match(/\^{(.*?)}/gi); + if (lstr != null) + for (i = 0; i < lstr.length; ++i) { + var symbol = lstr[i].replace(' ', ''); + symbol = symbol.replace('^{', ''); // &sup + symbol = symbol.replace('}', ''); // ; + str = str.replace(lstr[i], symbol); + } + while (str.indexOf('#/') != -1) + str = str.replace('#/', JSROOT.Painter.symbols_map['#/']); + for ( var x in JSROOT.Painter.symbols_map) { + while (str.indexOf(x) != -1) + str = str.replace(x, JSROOT.Painter.symbols_map[x]); + } + + // simple workaround for simple #splitline{first_line}{second_line} + if ((str.indexOf("#splitline{")==0) && (str.charAt(str.length-1)=="}")) { + var pos = str.indexOf("}{"); + if ((pos>0) && (pos == str.lastIndexOf("}{"))) { + str = str.replace("}{", "\n "); + str = str.slice(11, str.length-1); + } + } + + str = str.replace('^2','\xB2').replace('^3','\xB3'); + + return str; + } + + JSROOT.Painter.isAnyLatex = function(str) { + return (str.indexOf("#")>=0) || (str.indexOf("\\")>=0) || (str.indexOf("{")>=0); + } + + JSROOT.Painter.translateMath = function(str, kind, color) { + // function translate ROOT TLatex into MathJax format + + if (kind!=2) { + str = str.replace(/#LT/g, "\\langle"); + str = str.replace(/#GT/g, "\\rangle"); + str = str.replace(/#club/g, "\\clubsuit"); + str = str.replace(/#spade/g, "\\spadesuit"); + str = str.replace(/#heart/g, "\\heartsuit"); + str = str.replace(/#diamond/g, "\\diamondsuit"); + str = str.replace(/#voidn/g, "\\wp"); + str = str.replace(/#voidb/g, "f"); + str = str.replace(/#copyright/g, "(c)"); + str = str.replace(/#ocopyright/g, "(c)"); + str = str.replace(/#trademark/g, "TM"); + str = str.replace(/#void3/g, "TM"); + str = str.replace(/#oright/g, "R"); + str = str.replace(/#void1/g, "R"); + str = str.replace(/#3dots/g, "\\ldots"); + str = str.replace(/#lbar/g, "\\mid"); + str = str.replace(/#void8/g, "\\mid"); + str = str.replace(/#divide/g, "\\div"); + str = str.replace(/#Jgothic/g, "\\Im"); + str = str.replace(/#Rgothic/g, "\\Re"); + str = str.replace(/#doublequote/g, "\""); + str = str.replace(/#plus/g, "+"); + + str = str.replace(/#diamond/g, "\\diamondsuit"); + str = str.replace(/#voidn/g, "\\wp"); + str = str.replace(/#voidb/g, "f"); + str = str.replace(/#copyright/g, "(c)"); + str = str.replace(/#ocopyright/g, "(c)"); + str = str.replace(/#trademark/g, "TM"); + str = str.replace(/#void3/g, "TM"); + str = str.replace(/#oright/g, "R"); + str = str.replace(/#void1/g, "R"); + str = str.replace(/#3dots/g, "\\ldots"); + str = str.replace(/#lbar/g, "\\mid"); + str = str.replace(/#void8/g, "\\mid"); + str = str.replace(/#divide/g, "\\div"); + str = str.replace(/#Jgothic/g, "\\Im"); + str = str.replace(/#Rgothic/g, "\\Re"); + str = str.replace(/#doublequote/g, "\""); + str = str.replace(/#plus/g, "+"); + str = str.replace(/#minus/g, "-"); + str = str.replace(/#\//g, "/"); + str = str.replace(/#upoint/g, "."); + str = str.replace(/#aa/g, "\\mathring{a}"); + str = str.replace(/#AA/g, "\\mathring{A}"); + + str = str.replace(/#omicron/g, "o"); + str = str.replace(/#Alpha/g, "A"); + str = str.replace(/#Beta/g, "B"); + str = str.replace(/#Epsilon/g, "E"); + str = str.replace(/#Zeta/g, "Z"); + str = str.replace(/#Eta/g, "H"); + str = str.replace(/#Iota/g, "I"); + str = str.replace(/#Kappa/g, "K"); + str = str.replace(/#Mu/g, "M"); + str = str.replace(/#Nu/g, "N"); + str = str.replace(/#Omicron/g, "O"); + str = str.replace(/#Rho/g, "P"); + str = str.replace(/#Tau/g, "T"); + str = str.replace(/#Chi/g, "X"); + str = str.replace(/#varomega/g, "\\varpi"); + + str = str.replace(/#corner/g, "?"); + str = str.replace(/#ltbar/g, "?"); + str = str.replace(/#bottombar/g, "?"); + str = str.replace(/#notsubset/g, "?"); + str = str.replace(/#arcbottom/g, "?"); + str = str.replace(/#cbar/g, "?"); + str = str.replace(/#arctop/g, "?"); + str = str.replace(/#topbar/g, "?"); + str = str.replace(/#arcbar/g, "?"); + str = str.replace(/#downleftarrow/g, "?"); + str = str.replace(/#splitline/g, "\\genfrac{}{}{0pt}{}"); + str = str.replace(/#it/g, "\\textit"); + str = str.replace(/#bf/g, "\\textbf"); + + str = str.replace(/#frac/g, "\\frac"); + //str = str.replace(/#left{/g, "\\left\\{"); + //str = str.replace(/#right}/g, "\\right\\}"); + str = str.replace(/#left{/g, "\\lbrace"); + str = str.replace(/#right}/g, "\\rbrace"); + str = str.replace(/#left\[/g, "\\lbrack"); + str = str.replace(/#right\]/g, "\\rbrack"); + //str = str.replace(/#left/g, "\\left"); + //str = str.replace(/#right/g, "\\right"); + // processing of #[] #{} should be done + str = str.replace(/#\[\]{/g, "\\lbrack"); + str = str.replace(/ } /g, "\\rbrack"); + //str = str.replace(/#\[\]/g, "\\brack"); + //str = str.replace(/#{}/g, "\\brace"); + str = str.replace(/#\[/g, "\\lbrack"); + str = str.replace(/#\]/g, "\\rbrack"); + str = str.replace(/#{/g, "\\lbrace"); + str = str.replace(/#}/g, "\\rbrace"); + str = str.replace(/ /g, "\\;"); + + for (var x in JSROOT.Painter.symbols_map) { + var y = "\\" + x.substr(1); + str = str.replace(new RegExp(x,'g'), y); + } + } else { + str = str.replace(/\\\^/g, "\\hat"); + } + + if (typeof color != 'string') return "\\(" + str + "\\)"; + + if (color.indexOf("rgb(")>=0) + color = color.replace(/rgb/g, "[RGB]") + .replace(/\(/g, '{') + .replace(/\)/g, '}'); + return "\\(\\color{" + color + '}' + str + "\\)"; + } + + // ============================================================================== + + JSROOT.TBasePainter = function() { + this.divid = null; // either id of element (preferable) or element itself + } + + JSROOT.TBasePainter.prototype.Cleanup = function() { + // generic method to cleanup painter + } + + JSROOT.TBasePainter.prototype.DrawingReady = function() { + // function should be called by the painter when first drawing is completed + this._ready_called_ = true; + if ('_ready_callback_' in this) { + JSROOT.CallBack(this._ready_callback_, this); + delete this._ready_callback_; + } + return this; + } + + JSROOT.TBasePainter.prototype.WhenReady = function(callback) { + // call back will be called when painter ready with the drawing + if ('_ready_called_' in this) return JSROOT.CallBack(callback, this); + this._ready_callback_ = callback; + } + + JSROOT.TBasePainter.prototype.GetObject = function() { + return null; + } + + JSROOT.TBasePainter.prototype.MatchObjectType = function(typ) { + return false; + } + + JSROOT.TBasePainter.prototype.UpdateObject = function(obj) { + return false; + } + + JSROOT.TBasePainter.prototype.RedrawPad = function(resize) { + } + + JSROOT.TBasePainter.prototype.RedrawObject = function(obj) { + if (this.UpdateObject(obj)) { + var current = document.body.style.cursor; + document.body.style.cursor = 'wait'; + this.RedrawPad(); + document.body.style.cursor = current; + } + } + + JSROOT.TBasePainter.prototype.CheckResize = function(arg) { + return false; // indicate if resize is processed + } + + JSROOT.TBasePainter.prototype.select_main = function() { + // return d3.select for main element, defined with divid + if ((this.divid === null) || (this.divid === undefined)) return d3.select(null); + if ((typeof this.divid == "string") && + (this.divid.charAt(0) != "#")) return d3.select("#" + this.divid); + return d3.select(this.divid); + } + + JSROOT.TBasePainter.prototype.main_visible_rect = function() { + // return rect with width/height which correcpond to the visible area of drawing region + + var render_to = this.select_main(); + + var rect = render_to.node().getBoundingClientRect(); + + var res = {}; + + // this is size where canvas should be rendered + res.width = Math.round(rect.width - this.GetStyleValue(render_to, 'padding-left') - this.GetStyleValue(render_to, 'padding-right')); + res.height = Math.round(rect.height - this.GetStyleValue(render_to, 'padding-top') - this.GetStyleValue(render_to, 'padding-bottom')); + + return res; + } + + JSROOT.TBasePainter.prototype.SetDivId = function(divid) { + // base painter does not creates canvas or frames + // it registered in the first child element + if (arguments.length > 0) + this.divid = divid; + var main = this.select_main(); + var chld = main.node() ? main.node().firstChild : null; + if (chld) chld.painter = this; + } + + JSROOT.TBasePainter.prototype.SetItemName = function(name, opt) { + if (typeof name === 'string') this._hitemname = name; + else delete this._hitemname; + // only upate draw option, never delete. null specified when update drawing + if (typeof opt === 'string') this._hdrawopt = opt; + } + + JSROOT.TBasePainter.prototype.GetItemName = function() { + return ('_hitemname' in this) ? this._hitemname : null; + } + + JSROOT.TBasePainter.prototype.GetItemDrawOpt = function() { + return ('_hdrawopt' in this) ? this._hdrawopt : ""; + } + + JSROOT.TBasePainter.prototype.CanZoomIn = function(axis,left,right) { + // check if it makes sense to zoom inside specified axis range + return false; + } + + JSROOT.TBasePainter.prototype.GetStyleValue = function(select, name) { + var value = select.style(name); + if (!value) return 0; + value = parseFloat(value.replace("px","")); + return isNaN(value) ? 0 : value; + } + + // ============================================================================== + + JSROOT.TObjectPainter = function(obj) { + JSROOT.TBasePainter.call(this); + this.draw_g = null; // container for all drawn objects + this.pad_name = ""; // name of pad where object is drawn + this.main = null; // main painter, received from pad + this.draw_object = ((obj!==undefined) && (typeof obj == 'object')) ? obj : null; + } + + JSROOT.TObjectPainter.prototype = Object.create(JSROOT.TBasePainter.prototype); + + JSROOT.TObjectPainter.prototype.GetObject = function() { + return this.draw_object; + } + + JSROOT.TObjectPainter.prototype.MatchObjectType = function(arg) { + if ((arg === undefined) || (arg === null) || (this.draw_object===null)) return false; + if (typeof arg === 'string') return this.draw_object._typename === arg; + return (typeof arg === 'object') && (this.draw_object._typename === arg._typename); + } + + JSROOT.TObjectPainter.prototype.SetItemName = function(name, opt) { + JSROOT.TBasePainter.prototype.SetItemName.call(this, name, opt); + if (this.no_default_title || (name=="")) return; + var can = this.svg_canvas(); + if (!can.empty()) can.select("title").text(name); + else this.select_main().attr("title", name); + } + + JSROOT.TObjectPainter.prototype.UpdateObject = function(obj) { + // generic method to update object + // just copy all members from source object + if (!this.MatchObjectType(obj)) return false; + JSROOT.extend(this.GetObject(), obj); + return true; + } + + JSROOT.TObjectPainter.prototype.GetTipName = function(append) { + var res = this.GetItemName(); + if (res===null) res = ""; + if ((res.length === 0) && ('fName' in this.GetObject())) + res = this.GetObject().fName; + if (res.lenght > 20) res = res.substr(0,17)+"..."; + if ((res.length > 0) && (append!==undefined)) res += append; + return res; + } + + JSROOT.TObjectPainter.prototype.pad_painter = function(active_pad) { + var can = active_pad ? this.svg_pad() : this.svg_canvas(); + return can.empty() ? null : can.property('pad_painter'); + } + + JSROOT.TObjectPainter.prototype.CheckResize = function(arg) { + // no painter - no resize + var pad_painter = this.pad_painter(); + if (!pad_painter) return false; + + // only canvas should be checked + pad_painter.CheckCanvasResize(arg); + return true; + } + + JSROOT.TObjectPainter.prototype.RemoveDrawG = function() { + // generic method to delete all graphical elements, associated with painter + if (this.draw_g != null) { + this.draw_g.remove(); + this.draw_g = null; + } + } + + /** function (re)creates svg:g element used for specific object drawings + * either one attached svg:g to pad (take_pad==true) or to the frame (take_pad==false) + * svg:g element can be attached to different layers */ + JSROOT.TObjectPainter.prototype.RecreateDrawG = function(take_pad, layer) { + if (this.draw_g) { + // one should keep svg:g element on its place + d3.selectAll(this.draw_g.node().childNodes).remove(); + } else + if (take_pad) { + if (typeof layer != 'string') layer = "text_layer"; + if (layer.charAt(0) == ".") layer = layer.substr(1); + this.draw_g = this.svg_layer(layer).append("svg:g"); + } else { + if (typeof layer != 'string') layer = ".main_layer"; + if (layer.charAt(0) != ".") layer = "." + layer; + this.draw_g = this.svg_frame().select(layer).append("svg:g"); + } + + // set attributes for debugging + if (this.draw_object!==null) { + this.draw_g.attr('objname', this.draw_object.fName); + this.draw_g.attr('objtype', this.draw_object._typename); + } + + return this.draw_g; + } + + /** This is main graphical SVG element, where all Canvas drawing are performed */ + JSROOT.TObjectPainter.prototype.svg_canvas = function() { + return this.select_main().select(".root_canvas"); + } + + /** This is SVG element, correspondent to current pad */ + JSROOT.TObjectPainter.prototype.svg_pad = function(pad_name) { + var c = this.svg_canvas(); + if (pad_name === undefined) pad_name = this.pad_name; + if ((pad_name.length > 0) && !c.empty()) + c = c.select(".subpads_layer").select("[pad=" + pad_name + ']'); + return c; + } + + /** Method selects immediate layer under canvas/pad main element */ + JSROOT.TObjectPainter.prototype.svg_layer = function(name, pad_name) { + var svg = this.svg_pad(pad_name); + if (svg.empty()) return svg; + + var node = svg.node().firstChild; + + while (node!==null) { + var elem = d3.select(node); + if (elem.classed(name)) return elem; + node = node.nextSibling; + } + + return d3.select(null); + } + + JSROOT.TObjectPainter.prototype.CurrentPadName = function(new_name) { + var svg = this.svg_canvas(); + if (svg.empty()) return ""; + var curr = svg.property('current_pad'); + if (new_name !== undefined) svg.property('current_pad', new_name); + return curr; + } + + JSROOT.TObjectPainter.prototype.root_pad = function() { + var pad_painter = this.pad_painter(true); + return pad_painter ? pad_painter.pad : null; + } + + /** Converts pad x or y coordinate into NDC value */ + JSROOT.TObjectPainter.prototype.ConvertToNDC = function(axis, value, isndc) { + var pad = this.root_pad(); + if (isndc == null) isndc = false; + + if (isndc || (pad==null)) return value; + + if (axis=="y") { + if (pad.fLogy) + value = (value>0) ? JSROOT.log10(value) : pad.fUymin; + return (value - pad.fY1) / (pad.fY2 - pad.fY1); + } + if (pad.fLogx) + value = (value>0) ? JSROOT.log10(value) : pad.fUxmin; + return (value - pad.fX1) / (pad.fX2 - pad.fX1); + } + + /** Converts x or y coordinate into SVG coordinates, + * which could be used directly for drawing. + * Parameters: axis should be "x" or "y", value to convert, is ndc should be used */ + JSROOT.TObjectPainter.prototype.AxisToSvg = function(axis, value, ndc) { + var main = this.main_painter(); + if ((main!=null) && !ndc) + return axis=="y" ? main.gry(value) : main.grx(value); + if (!ndc) value = this.ConvertToNDC(axis, value); + if (axis=="y") return (1-value)*this.pad_height(); + return value*this.pad_width(); + } + + JSROOT.TObjectPainter.prototype.PadToSvg = function(axis, value, ndc) { + return this.AxisToSvg(axis,value,ndc); + } + + /** This is SVG element with current frame */ + JSROOT.TObjectPainter.prototype.svg_frame = function() { + return this.svg_pad().select(".root_frame"); + } + + JSROOT.TObjectPainter.prototype.frame_painter = function() { + var res = this.svg_frame().property('frame_painter'); + return (res===undefined) ? null : res; + } + + JSROOT.TObjectPainter.prototype.pad_width = function(pad_name) { + var res = this.svg_pad(pad_name).property("draw_width"); + return isNaN(res) ? 0 : res; + } + + JSROOT.TObjectPainter.prototype.pad_height = function(pad_name) { + var res = this.svg_pad(pad_name).property("draw_height"); + return isNaN(res) ? 0 : res; + } + + JSROOT.TObjectPainter.prototype.frame_x = function() { + var res = parseInt(this.svg_frame().attr("x")); + return isNaN(res) ? 0 : res; + } + + JSROOT.TObjectPainter.prototype.frame_y = function() { + var res = parseInt(this.svg_frame().attr("y")); + return isNaN(res) ? 0 : res; + } + + JSROOT.TObjectPainter.prototype.frame_width = function() { + var res = parseInt(this.svg_frame().attr("width")); + return isNaN(res) ? 0 : res; + } + + JSROOT.TObjectPainter.prototype.frame_height = function() { + var res = parseInt(this.svg_frame().attr("height")); + return isNaN(res) ? 0 : res; + } + + JSROOT.TObjectPainter.prototype.embed_3d = function() { + // returns embed mode for 3D drawings (three.js) inside SVG + // 0 - no embedding, 3D drawing take full size of canvas + // 1 - no embedding, canvas placed over svg with proper size (resize problem may appear) + // 2 - normall embedding via ForeginObject, works only with Firefox + + if (JSROOT.gStyle.Embed3DinSVG < 2) return JSROOT.gStyle.Embed3DinSVG; + if (JSROOT.browser.isFirefox /*|| JSROOT.browser.isWebKit*/) + return JSROOT.gStyle.Embed3DinSVG; // use specified mode + return 1; // default is overlay + } + + JSROOT.TObjectPainter.prototype.access_3d_kind = function(new_value) { + + var svg = this.svg_pad(); + if (svg.empty()) return -1; + + // returns kind of currently created 3d canvas + var kind = svg.property('can3d'); + if (new_value !== undefined) svg.property('can3d', new_value); + return ((kind===null) || (kind===undefined)) ? -1 : kind; + } + + JSROOT.TObjectPainter.prototype.size_for_3d = function(can3d) { + // one uses frame sizes for the 3D drawing - like TH2/TH3 objects + + if (can3d === undefined) can3d = this.embed_3d(); + + var pad = this.svg_pad(); + + var clname = this.pad_name; + if (clname == '') clname = 'canvas'; + clname = "draw3d_" + clname; + + if (pad.empty()) { + // this is a case when object drawn without canvas + + var rect = this.main_visible_rect(); + + if ((rect.height<10) && (rect.width>10)) { + rect.height = Math.round(0.66*rect.width); + this.select_main().style('height', rect.height + "px"); + } + rect.x = 0; rect.y = 0; rect.clname = clname; rect.can3d = -1; + return rect; + } + + var elem = pad; + if (can3d == 0) elem = this.svg_canvas(); + + var size = { x: 0, y: 0, width: 100, height:100, clname: clname, can3d: can3d }; + + if (this.frame_painter()!==null) { + elem = this.svg_frame(); + size.x = elem.property("draw_x"); + size.y = elem.property("draw_y"); + } + + size.width = elem.property("draw_width"); + size.height = elem.property("draw_height"); + + if ((this.frame_painter()===null) && (can3d > 0)) { + size.x = Math.round(size.x + size.width*0.1); + size.y = Math.round(size.y + size.height*0.1); + size.width = Math.round(size.width*0.8); + size.height = Math.round(size.height*0.8); + } + + if (can3d === 1) + this.CalcAbsolutePosition(this.svg_pad(), size); + + return size; + } + + + JSROOT.TObjectPainter.prototype.clear_3d_canvas = function() { + var can3d = this.access_3d_kind(null); + if (can3d < 0) return; + + var size = this.size_for_3d(can3d); + + if (size.can3d === 0) { + d3.select(this.svg_canvas().node().nextSibling).remove(); // remove html5 canvas + this.svg_canvas().style('display', null); // show SVG canvas + } else { + if (this.svg_pad().empty()) return; + + this.apply_3d_size(size).remove(); + + this.svg_frame().style('display', null); + } + } + + JSROOT.TObjectPainter.prototype.add_3d_canvas = function(size, canv) { + + if ((canv == null) || (size.can3d < -1)) return; + + if (size.can3d === -1) { + // case when 3D object drawn without canvas + + var main = this.select_main().node(); + if (main !== null) { + main.appendChild(canv); + canv['painter'] = this; + } + + return; + } + + this.access_3d_kind(size.can3d); + + if (size.can3d === 0) { + this.svg_canvas().style('display', 'none'); // hide SVG canvas + + this.svg_canvas().node().parentNode.appendChild(canv); // add directly + } else { + if (this.svg_pad().empty()) return; + + // first hide normal frame + this.svg_frame().style('display', 'none'); + + var elem = this.apply_3d_size(size); + + elem.attr('title','').node().appendChild(canv); + } + } + + JSROOT.TObjectPainter.prototype.apply_3d_size = function(size, onlyget) { + + if (size.can3d < 0) return d3.select(null); + + var elem; + + if (size.can3d > 1) { + + var layer = this.svg_layer("special_layer"); + + elem = layer.select("." + size.clname); + if (onlyget) return elem; + + if (elem.empty()) + elem = layer.append("foreignObject").attr("class", size.clname); + + elem.attr('x', size.x) + .attr('y', size.y) + .attr('width', size.width) + .attr('height', size.height) + .attr('viewBox', "0 0 " + size.width + " " + size.height) + .attr('preserveAspectRatio','xMidYMid'); + + } else { + var prnt = this.svg_canvas().node().parentNode; + + elem = d3.select(prnt).select("." + size.clname); + if (onlyget) return elem; + + // force redraw by resize + this.svg_canvas().property('redraw_by_resize', true); + + if (elem.empty()) + elem = d3.select(prnt).append('div').attr("class", size.clname); + + // our position inside canvas, but to set 'absolute' position we should use + // canvas element offset relative to first parent with position + var offx = 0, offy = 0; + while (prnt && !offx && !offy) { + if (getComputedStyle(prnt).position !== 'static') break; + offx += prnt.offsetLeft; + offy += prnt.offsetTop; + prnt = prnt.parentNode; + } + + elem.style('position','absolute') + .style('left', (size.x + offx) + 'px') + .style('top', (size.y + offy) + 'px') + .style('width', size.width + 'px') + .style('height', size.height + 'px'); + } + + return elem; + } + + + /** Returns main pad painter - normally TH1/TH2 painter, which draws all axis */ + JSROOT.TObjectPainter.prototype.main_painter = function() { + if (this.main === null) { + var svg_p = this.svg_pad(); + if (!svg_p.empty()) { + this.main = svg_p.property('mainpainter'); + if (this.main === undefined) this.main = null; + } + } + return this.main; + } + + JSROOT.TObjectPainter.prototype.is_main_painter = function() { + return this === this.main_painter(); + } + + JSROOT.TObjectPainter.prototype.SetDivId = function(divid, is_main, pad_name) { + // Assigns id of top element (normally
    where drawing is done + // is_main - -1 - not add to painters list, + // 0 - normal painter (default), + // 1 - major objects like TH1/TH2 (required canvas with frame) + // 2 - if canvas missing, create it, but not set as main object + // 3 - if canvas and (or) frame missing, create them, but not set as main object + // 4 - major objects like TH3 (required canvas, but no frame) + // 5 - major objects like TGeoVolume (do not require canvas) + // pad_name - when specified, subpad name used for object drawin + // In some situations canvas may not exists - for instance object drawn as html, not as svg. + // In such case the only painter will be assigned to the first element + + if (divid !== undefined) + this.divid = divid; + + if ((is_main === null) || (is_main === undefined)) is_main = 0; + + this.create_canvas = false; + + // SVG element where canvas is drawn + var svg_c = this.svg_canvas(); + + if (svg_c.empty() && (is_main > 0) && (is_main!==5)) { + JSROOT.Painter.drawCanvas(divid, null, ((is_main == 2) || (is_main == 4)) ? "noframe" : ""); + svg_c = this.svg_canvas(); + this.create_canvas = true; + } + + if (svg_c.empty()) { + if ((is_main < 0) || (is_main===5) || this.iscan) return; + var main = this.select_main(); + if (main.node() && main.node().firstChild) + main.node().firstChild.painter = this; + return; + } + + // SVG element where current pad is drawn (can be canvas itself) + this.pad_name = pad_name; + if (this.pad_name === undefined) + this.pad_name = this.CurrentPadName(); + + if (is_main < 0) return; + + // create TFrame element if not exists + if (this.svg_frame().select(".main_layer").empty() && ((is_main == 1) || (is_main == 3))) { + JSROOT.Painter.drawFrame(divid, null); + if (this.svg_frame().empty()) return alert("Fail to draw dummy TFrame"); + } + + var svg_p = this.svg_pad(); + if (svg_p.empty()) return; + + if (svg_p.property('pad_painter') !== this) + svg_p.property('pad_painter').painters.push(this); + + if (((is_main === 1) || (is_main === 4) || (is_main === 5)) && !svg_p.property('mainpainter')) + // when this is first main painter in the pad + svg_p.property('mainpainter', this); + } + + JSROOT.TObjectPainter.prototype.CalcAbsolutePosition = function(sel, pos) { + while (!sel.empty() && !sel.classed('root_canvas')) { + if (sel.classed('root_frame') || sel.classed('root_pad')) { + pos.x += sel.property("draw_x"); + pos.y += sel.property("draw_y"); + } + sel = d3.select(sel.node().parentNode); + } + return pos; + } + + + JSROOT.TObjectPainter.prototype.createAttFill = function(attfill, pattern, color, kind) { + + // fill kind can be 1 or 2 + // 1 means object drawing where combination fillcolor==0 and fillstyle==1001 means no filling + // 2 means all other objects where such combination is white-color filling + + var fill = { color: "none", colorindx: 0, pattern: 0, used: true, kind: 2, changed: false }; + + if (kind!==undefined) fill.kind = kind; + + fill.Apply = function(selection) { + this.used = true; + + selection.style('fill', this.color); + + if ('opacity' in this) + selection.style('opacity', this.opacity); + + if ('antialias' in this) + selection.style('antialias', this.antialias); + } + fill.func = fill.Apply.bind(fill); + + fill.Change = function(color, pattern, svg) { + this.changed = true; + + if ((color !== undefined) && !isNaN(color)) + this.colorindx = color; + + if ((pattern !== undefined) && !isNaN(pattern)) { + this.pattern = pattern; + delete this.opacity; + delete this.antialias; + } + + if (this.pattern < 1001) { + this.color = 'none'; + return true; + } + + if ((this.pattern === 1001) && (this.colorindx===0) && (this.kind===1)) { + this.color = 'none'; + return true; + } + + this.color = JSROOT.Painter.root_colors[this.colorindx]; + if (typeof this.color != 'string') this.color = "none"; + + if (this.pattern === 1001) return true; + + if ((this.pattern >= 4000) && (this.pattern <= 4100)) { + // special transparent colors (use for subpads) + this.opacity = (this.pattern - 4000)/100; + return true; + } + + if ((svg===undefined) || svg.empty() || (this.pattern < 3000) || (this.pattern > 3025)) return false; + + var id = "pat_" + this.pattern + "_" + this.colorindx; + + var defs = svg.select('defs'); + if (defs.empty()) + defs = svg.insert("svg:defs",":first-child"); + + var line_color = this.color; + this.color = "url(#" + id + ")"; + this.antialias = false; + + if (!defs.select("."+id).empty()) return true; + + var patt = defs.append('svg:pattern').attr("id", id).attr("class",id).attr("patternUnits","userSpaceOnUse"); + + switch (this.pattern) { + case 3001: + patt.attr("width", 2).attr("height", 2); + patt.append('svg:rect').attr("x", 0).attr("y", 0).attr("width", 1).attr("height", 1); + patt.append('svg:rect').attr("x", 1).attr("y", 1).attr("width", 1).attr("height", 1); + break; + case 3002: + patt.attr("width", 4).attr("height", 2); + patt.append('svg:rect').attr("x", 1).attr("y", 0).attr("width", 1).attr("height", 1); + patt.append('svg:rect').attr("x", 3).attr("y", 1).attr("width", 1).attr("height", 1); + break; + case 3003: + patt.attr("width", 4).attr("height", 4); + patt.append('svg:rect').attr("x", 2).attr("y", 1).attr("width", 1).attr("height", 1); + patt.append('svg:rect').attr("x", 0).attr("y", 3).attr("width", 1).attr("height", 1); + break; + case 3005: + patt.attr("width", 8).attr("height", 8); + patt.append("svg:line").attr("x1", 0).attr("y1", 0).attr("x2", 8).attr("y2", 8); + break; + case 3006: + patt.attr("width", 4).attr("height", 4); + patt.append("svg:line").attr("x1", 1).attr("y1", 0).attr("x2", 1).attr("y2", 3); + break; + case 3007: + patt.attr("width", 4).attr("height", 4); + patt.append("svg:line").attr("x1", 0).attr("y1", 1).attr("x2", 3).attr("y2", 1); + break; + case 3010: // bricks + patt.attr("width", 10).attr("height", 10); + patt.append("svg:line").attr("x1", 0).attr("y1", 2).attr("x2", 10).attr("y2", 2); + patt.append("svg:line").attr("x1", 0).attr("y1", 7).attr("x2", 10).attr("y2", 7); + patt.append("svg:line").attr("x1", 2).attr("y1", 0).attr("x2", 2).attr("y2", 2); + patt.append("svg:line").attr("x1", 7).attr("y1", 2).attr("x2", 7).attr("y2", 7); + patt.append("svg:line").attr("x1", 2).attr("y1", 7).attr("x2", 2).attr("y2", 10); + break; + case 3021: // stairs + case 3022: + patt.attr("width", 10).attr("height", 10); + patt.append("svg:line").attr("x1", 0).attr("y1", 5).attr("x2", 5).attr("y2", 5); + patt.append("svg:line").attr("x1", 5).attr("y1", 5).attr("x2", 5).attr("y2", 0); + patt.append("svg:line").attr("x1", 5).attr("y1", 10).attr("x2", 10).attr("y2", 10); + patt.append("svg:line").attr("x1", 10).attr("y1", 10).attr("x2", 10).attr("y2", 5); + break; + default: /* == 3004 */ + patt.attr("width", 8).attr("height", 8); + patt.append("svg:line").attr("x1", 8).attr("y1", 0).attr("x2", 0).attr("y2", 8); + break; + } + + patt.selectAll('line').style("stroke",line_color).style("stroke-width", 1); + patt.selectAll('rect').style("fill",line_color); + + return true; + } + + if ((attfill!==null) && (typeof attfill == 'object')) { + if ('fFillStyle' in attfill) pattern = attfill.fFillStyle; + if ('fFillColor' in attfill) color = attfill.fFillColor; + } + + fill.Change(color, pattern, this.svg_canvas()); + + fill.changed = false; + + return fill; + } + + JSROOT.TObjectPainter.prototype.ForEachPainter = function(userfunc) { + // Iterate over all known painters + + var main = this.select_main(); + var painter = (main.node() && main.node().firstChild) ? main.node().firstChild['painter'] : null; + if (painter!=null) return userfunc(painter); + + var pad_painter = this.pad_painter(true); + if (pad_painter == null) return; + + userfunc(pad_painter); + if ('painters' in pad_painter) + for (var k = 0; k < pad_painter.painters.length; ++k) + userfunc(pad_painter.painters[k]); + } + + JSROOT.TObjectPainter.prototype.Cleanup = function() { + // generic method to cleanup painters + this.select_main().html(""); + } + + JSROOT.TObjectPainter.prototype.RedrawPad = function() { + // call Redraw methods for each painter in the frame + // if selobj specified, painter with selected object will be redrawn + var pad_painter = this.pad_painter(true); + if (pad_painter) pad_painter.Redraw(); + } + + JSROOT.TObjectPainter.prototype.SwitchTooltip = function(on) { + var fp = this.frame_painter(); + if (fp) fp.ProcessTooltipEvent(null, on); + } + + JSROOT.TObjectPainter.prototype.AddDrag = function(callback) { + if (!JSROOT.gStyle.MoveResize) return; + + var pthis = this; + + var rect_width = function() { return Number(pthis.draw_g.attr("width")); }; + var rect_height = function() { return Number(pthis.draw_g.attr("height")); }; + + var acc_x = 0, acc_y = 0, pad_w = 1, pad_h = 1, drag_tm = null; + + function detectRightButton(event) { + if ('buttons' in event) return event.buttons === 2; + else if ('which' in event) return event.which === 3; + else if ('button' in event) return event.button === 2; + return false; + } + + var resize_corner1 = this.draw_g.select('.resize_corner1'); + if (resize_corner1.empty()) + resize_corner1 = this.draw_g + .append("path") + .attr('class','resize_corner1') + .attr("d","M2,2 h15 v-5 h-20 v20 h5 Z"); + + var resize_corner2 = this.draw_g.select('.resize_corner2'); + if (resize_corner2.empty()) + resize_corner2 = this.draw_g + .append("path") + .attr('class','resize_corner2') + .attr("d","M-2,-2 h-15 v5 h20 v-20 h-5 Z"); + + resize_corner1.style("opacity", "0") + .style("cursor", "nw-resize"); + + resize_corner2.style("opacity", "0") + .style("cursor", "se-resize") + .attr("transform", "translate(" + rect_width() + "," + rect_height() + ")"); + + var drag_rect = null; + + function complete_drag() { + drag_rect.style("cursor", "auto"); + + var oldx = Number(pthis.draw_g.attr("x")), + oldy = Number(pthis.draw_g.attr("y")), + newx = Number(drag_rect.attr("x")), + newy = Number(drag_rect.attr("y")), + newwidth = Number(drag_rect.attr("width")), + newheight = Number(drag_rect.attr("height")); + + if (callback.minwidth && newwidth < callback.minwidth) newwidth = callback.minwidth; + if (callback.minheight && newheight < callback.minheight) newheight = callback.minheight; + + + var change_size = (newwidth !== rect_width()) || (newheight !== rect_height()); + var change_pos = (newx !== oldx) || (newy !== oldy); + + pthis.draw_g.attr('x', newx).attr('y', newy) + .attr("transform", "translate(" + newx + "," + newy + ")") + .attr('width', newwidth).attr('height', newheight); + + drag_rect.remove(); + drag_rect = null; + + pthis.SwitchTooltip(true); + + resize_corner2.attr("transform", "translate(" + newwidth + "," + newheight + ")"); + + if (change_size || change_pos) { + if (change_size && ('resize' in callback)) callback.resize(newwidth, newheight); + if (change_pos && ('move' in callback)) callback.move(newx, newy, newx - oldxx, newy-oldy); + + if (change_size || change_pos) { + if ('obj' in callback) { + callback.obj.fX1NDC = newx / pthis.pad_width(); + callback.obj.fX2NDC = (newx + newwidth) / pthis.pad_width(); + callback.obj.fY1NDC = 1 - (newy + newheight) / pthis.pad_height(); + callback.obj.fY2NDC = 1 - newy / pthis.pad_height(); + callback.obj.modified_NDC = true; // indicate that NDC was interactively changed, block in updated + } + if ('redraw' in callback) callback.redraw(); + } + } + + return change_size || change_pos; + } + + var drag_move = d3.behavior.drag().origin(Object) + .on("dragstart", function() { + if (detectRightButton(d3.event.sourceEvent)) return; + + JSROOT.Painter.closeMenu(); // close menu + + pthis.SwitchTooltip(false); // disable tooltip + + d3.event.sourceEvent.preventDefault(); + d3.event.sourceEvent.stopPropagation(); + + acc_x = 0; acc_y = 0; + pad_w = pthis.pad_width() - rect_width(); + pad_h = pthis.pad_height() - rect_height(); + + drag_tm = new Date(); + + drag_rect = d3.select(pthis.draw_g.node().parentNode).append("rect") + .classed("zoom", true) + .attr("x", pthis.draw_g.attr("x")) + .attr("y", pthis.draw_g.attr("y")) + .attr("width", rect_width()) + .attr("height", rect_height()) + .style("cursor", "move") + .style("pointer-events","none"); // let forward double click to underlying elements + }).on("drag", function() { + if (drag_rect == null) return; + + d3.event.sourceEvent.preventDefault(); + + var x = Number(drag_rect.attr("x")), y = Number(drag_rect.attr("y")); + var dx = d3.event.dx, dy = d3.event.dy; + + if ((acc_x<0) && (dx>0)) { acc_x+=dx; dx=0; if (acc_x>0) { dx=acc_x; acc_x=0; }} + if ((acc_x>0) && (dx<0)) { acc_x+=dx; dx=0; if (acc_x<0) { dx=acc_x; acc_x=0; }} + if ((acc_y<0) && (dy>0)) { acc_y+=dy; dy=0; if (acc_y>0) { dy=acc_y; acc_y=0; }} + if ((acc_y>0) && (dy<0)) { acc_y+=dy; dy=0; if (acc_y<0) { dy=acc_y; acc_y=0; }} + + if (x+dx<0) { acc_x+=(x+dx); x=0; } else + if (x+dx>pad_w) { acc_x+=(x+dx-pad_w); x=pad_w; } else x+=dx; + + if (y+dy<0) { acc_y+=(y+dy); y = 0; } else + if (y+dy>pad_h) { acc_y+=(y+dy-pad_h); y=pad_h; } else y+=dy; + + drag_rect.attr("x", x).attr("y", y); + + d3.event.sourceEvent.stopPropagation(); + }).on("dragend", function() { + if (drag_rect==null) return; + + d3.event.sourceEvent.preventDefault(); + + if (complete_drag() === false) + if(callback['ctxmenu'] && ((new Date()).getTime() - drag_tm.getTime() > 600)) { + var rrr = resize_corner2.node().getBoundingClientRect(); + pthis.ShowContextMenu('main', { clientX: rrr.left, clientY: rrr.top } ); + } + }); + + var drag_resize = d3.behavior.drag().origin(Object) + .on( "dragstart", function() { + if (detectRightButton(d3.event.sourceEvent)) return; + + d3.event.sourceEvent.stopPropagation(); + d3.event.sourceEvent.preventDefault(); + + pthis.SwitchTooltip(false); // disable tooltip + + acc_x = 0; acc_y = 0; + pad_w = pthis.pad_width(); + pad_h = pthis.pad_height(); + drag_rect = d3.select(pthis.draw_g.node().parentNode).append("rect") + .classed("zoom", true) + .attr("x", pthis.draw_g.attr("x")) + .attr("y", pthis.draw_g.attr("y")) + .attr("width", rect_width()) + .attr("height", rect_height()) + .style("cursor", d3.select(this).style("cursor")); + }).on("drag", function() { + if (drag_rect == null) return; + + d3.event.sourceEvent.preventDefault(); + + var w = Number(drag_rect.attr("width")), h = Number(drag_rect.attr("height")), + x = Number(drag_rect.attr("x")), y = Number(drag_rect.attr("y")); + var dx = d3.event.dx, dy = d3.event.dy; + if ((acc_x<0) && (dx>0)) { acc_x+=dx; dx=0; if (acc_x>0) { dx=acc_x; acc_x=0; }} + if ((acc_x>0) && (dx<0)) { acc_x+=dx; dx=0; if (acc_x<0) { dx=acc_x; acc_x=0; }} + if ((acc_y<0) && (dy>0)) { acc_y+=dy; dy=0; if (acc_y>0) { dy=acc_y; acc_y=0; }} + if ((acc_y>0) && (dy<0)) { acc_y+=dy; dy=0; if (acc_y<0) { dy=acc_y; acc_y=0; }} + + if (d3.select(this).classed('resize_corner1')) { + if (x+dx < 0) { acc_x += (x+dx); w += x; x = 0; } else + if (w-dx < 0) { acc_x -= (w-dx); x += w; w = 0; } else { x+=dx; w-=dx; } + if (y+dy < 0) { acc_y += (y+dy); h += y; y = 0; } else + if (h-dy < 0) { acc_y -= (h-dy); y += h; h = 0; } else { y+=dy; h-=dy; } + } else { + if (x+w+dx > pad_w) { acc_x += (x+w+dx-pad_w); w = pad_w-x; } else + if (w+dx < 0) { acc_x += (w+dx); w = 0; } else w += dx; + if (y+h+dy > pad_h) { acc_y += (y+h+dy-pad_h); h = pad_h-y; } else + if (h+dy < 0) { acc_y += (h+dy); h=0; } else h += dy; + } + + drag_rect.attr("x", x).attr("y", y).attr("width", w).attr("height", h); + + d3.event.sourceEvent.stopPropagation(); + }).on( "dragend", function() { + if (drag_rect == null) return; + + d3.event.sourceEvent.preventDefault(); + + complete_drag(); + }); + + if (!('only_resize' in callback)) { + this.draw_g.style("cursor", "move").call(drag_move); + } + + resize_corner1.call(drag_resize); + resize_corner2.call(drag_resize); + } + + JSROOT.TObjectPainter.prototype.startTouchMenu = function(kind) { + // method to let activate context menu via touch handler + + var arr = d3.touches(this.svg_frame().node()); + if (arr.length != 1) return; + + if (!kind || (kind=="")) kind = "main"; + var fld = "touch_" + kind; + + d3.event.preventDefault(); + d3.event.stopPropagation(); + + this[fld] = { dt: new Date(), pos: arr[0] }; + + this.svg_frame().on("touchcancel", this.endTouchMenu.bind(this, kind)) + .on("touchend", this.endTouchMenu.bind(this, kind)); + } + + JSROOT.TObjectPainter.prototype.endTouchMenu = function(kind) { + var fld = "touch_" + kind; + + if (! (fld in this)) return; + + d3.event.preventDefault(); + d3.event.stopPropagation(); + + var diff = new Date().getTime() - this[fld].dt.getTime(); + + this.svg_frame().on("touchcancel", null) + .on("touchend", null); + + if (diff>500) { + var rect = this.svg_frame().node().getBoundingClientRect(); + this.ShowContextMenu(kind, { clientX: rect.left + this[fld].pos[0], + clientY: rect.top + this[fld].pos[1] } ); + } + + delete this[fld]; + } + + JSROOT.TObjectPainter.prototype.AddColorMenuEntry = function(menu, name, value, set_func, fill_kind) { + if (value === undefined) return; + menu.add("sub:"+name, function() { + // todo - use jqury dialog here + var useid = (typeof value !== 'string'); + var col = prompt("Enter color " + (useid ? "(only id number)" : "(name or id)"), value); + if (col == null) return; + var id = parseInt(col); + if (!isNaN(id) && (JSROOT.Painter.root_colors[id] !== undefined)) { + col = JSROOT.Painter.root_colors[id]; + } else { + if (useid) return; + } + set_func.bind(this)(useid ? id : col); + }); + var useid = (typeof value !== 'string'); + for (var n=-1;n<11;++n) { + if ((n<0) && useid) continue; + if ((n==10) && (fill_kind!==1)) continue; + var col = (n<0) ? 'none' : JSROOT.Painter.root_colors[n]; + if ((n==0) && (fill_kind==1)) col = 'none'; + var svg = ""+col+""; + menu.addchk((value == (useid ? n : col)), svg, (useid ? n : col), set_func); + } + menu.add("endsub:"); + } + + JSROOT.TObjectPainter.prototype.AddSizeMenuEntry = function(menu, name, min, max, step, value, set_func) { + if (value === undefined) return; + + menu.add("sub:"+name, function() { + // todo - use jqury dialog here + var entry = value.toFixed(4); + if (step>=0.1) entry = value.toFixed(2); + if (step>=1) entry = value.toFixed(0); + var val = prompt("Enter value of " + name, entry); + if (val==null) return; + var val = parseFloat(val); + if (!isNaN(val)) set_func.bind(this)((step>=1) ? Math.round(val) : val); + }); + for (var val=min;val<=max;val+=step) { + var entry = val.toFixed(2); + if (step>=0.1) entry = val.toFixed(1); + if (step>=1) entry = val.toFixed(0); + menu.addchk((Math.abs(value - val) < step/2), entry, val, set_func); + } + menu.add("endsub:"); + } + + + JSROOT.TObjectPainter.prototype.OpenWebsocket = function() { + // create websocket for current object (canvas) + // via websocket one recieved many extra information + + delete this._websocket; + + var path = window.location.href; + path = path.replace("http://", "ws://"); + path = path.replace("https://", "wss://"); + var pos = path.indexOf("draw.htm"); + if (pos < 0) return; + + path = path.substr(0,pos) + "root.websocket"; + + console.log('open websocket ' + path); + + var conn = new WebSocket(path); + + this._websocket = conn; + + var pthis = this, sum1 = 0, sum2 = 0, cnt = 0; + + conn.onopen = function() { + console.log('websocket initialized'); + conn.send('READY'); // indicate that we are ready to recieve JSON code (or any other big peace) + } + + conn.onmessage = function (e) { + var d = e.data; + if (typeof d != 'string') return console.log("msg",d); + + if (d.substr(0,4)=='JSON') { + var obj = JSROOT.parse(d.substr(4)); + // console.log("get JSON ", d.length-4, obj._typename); + var tm1 = new Date().getTime(); + pthis.RedrawObject(obj); + var tm2 = new Date().getTime(); + sum1+=1; + sum2+=(tm2-tm1); + if (sum1>10) { console.log('Redraw ', Math.round(sum2/sum1)); sum1=sum2=0; } + + conn.send('READY'); // send ready message back + // if (++cnt > 10) conn.close(); + + } else + if (d.substr(0,4)=='MENU') { + var lst = JSROOT.parse(d.substr(4)); + console.log("get MENUS ", typeof lst, lst.length, d.length-4); + conn.send('READY'); // send ready message back + if (typeof pthis._getmenu_callback == 'function') + pthis._getmenu_callback(lst); + } else { + console.log("msg",d); + } + } + + conn.onclose = function() { + console.log('websocket closed'); + + delete pthis._websocket; + } + + conn.onerror = function (err) { + console.log("err",err); + conn.close(); + } + } + + + JSROOT.TObjectPainter.prototype.FillObjectExecMenu = function(menu, call_back) { + + if (!('_websocket' in this) || ('_getmenu_callback' in this)) + return JSROOT.CallBack(call_back); + + function DoExecMenu(arg) { + console.log('execute method ' + arg); + + if (this._websocket) + this._websocket.send('EXEC'+arg); + } + + function DoFillMenu(_menu, _call_back, items) { + + // avoid multiple call of the callback after timeout + if (!this._getmenu_callback) return; + delete this._getmenu_callback; + + if (items && items.length) { + _menu.add("separator"); + _menu.add("sub:Online"); + + for (var n=0;n"; + + menu.addchk((this.lineatt.dash==style), svg, style, function(arg) { this.lineatt.Change(undefined, undefined, arg); this.Redraw(); }.bind(this)); + } + menu.add("endsub:"); + menu.add("endsub:"); + + if (('excl_side' in this.lineatt) && (this.lineatt.excl_side!==0)) { + menu.add("sub:Exclusion"); + menu.add("sub:side"); + for (var side=-1;side<=1;++side) + menu.addchk((this.lineatt.excl_side==side), side, side, function(arg) { + this.lineatt.ChangeExcl(parseInt(arg)); + this.Redraw(); + }.bind(this)); + menu.add("endsub:"); + + this.AddSizeMenuEntry(menu, "width", 10, 100, 10, this.lineatt.excl_width, + function(arg) { this.lineatt.ChangeExcl(undefined, parseInt(arg)); this.Redraw(); }.bind(this)); + + menu.add("endsub:"); + } + } + + if (this.fillatt && this.fillatt.used) { + menu.add("sub:"+preffix+"Fill att"); + this.AddColorMenuEntry(menu, "color", this.fillatt.colorindx, + function(arg) { this.fillatt.Change(parseInt(arg), undefined, this.svg_canvas()); this.Redraw(); }.bind(this), this.fillatt.kind); + menu.add("sub:style", function() { + var id = prompt("Enter fill style id (1001-solid, 3000..3010)", this.fillatt.pattern); + if (id == null) return; + id = parseInt(id); + if (isNaN(id)) return; + this.fillatt.Change(undefined, id, this.svg_canvas()); + this.Redraw(); + }.bind(this)); + + var supported = [1, 1001, 3001, 3002, 3003, 3004, 3005, 3006, 3007, 3010, 3021, 3022]; + + var clone = JSROOT.clone(this.fillatt); + if (clone.colorindx<=0) clone.colorindx = 1; + + for (var n=0; n"; + + menu.addchk(this.fillatt.pattern == supported[n], svg, supported[n], function(arg) { + this.fillatt.Change(undefined, parseInt(arg), this.svg_canvas()); + this.Redraw(); + }.bind(this)); + } + menu.add("endsub:"); + menu.add("endsub:"); + } + + if (this.markeratt && this.markeratt.used) { + menu.add("sub:"+preffix+"Marker att"); + this.AddColorMenuEntry(menu, "color", this.markeratt.color, + function(arg) { this.markeratt.Change(arg); this.Redraw(); }.bind(this)); + this.AddSizeMenuEntry(menu, "size", 0.5, 6, 0.5, this.markeratt.size, + function(arg) { this.markeratt.Change(undefined, undefined, parseFloat(arg)); this.Redraw(); }.bind(this)); + + menu.add("sub:style"); + var supported = [1,2,3,4,5,6,7,8,21,22,23,24,25,26,27,28,29,30,31,32,33,34]; + + var clone = JSROOT.clone(this.markeratt); + for (var n=0; n"; + + menu.addchk(this.markeratt.style == supported[n], svg, supported[n], + function(arg) { this.markeratt.Change(undefined, parseInt(arg)); this.Redraw(); }.bind(this)); + } + menu.add("endsub:"); + menu.add("endsub:"); + } + } + + JSROOT.TObjectPainter.prototype.TextAttContextMenu = function(menu, prefix) { + // for the moment, text attributes accessed directly from objects + + var obj = this.GetObject(); + if (!obj || !('fTextColor' in obj)) return; + + menu.add("sub:" + (prefix ? prefix : "Text")); + this.AddColorMenuEntry(menu, "color", obj.fTextColor, + function(arg) { this.GetObject().fTextColor = parseInt(arg); this.Redraw(); }.bind(this)); + + var align = [11, 12, 13, 21, 22, 23, 31, 32, 33], + hnames = ['left', 'centered' , 'right'], + vnames = ['bottom', 'centered', 'top']; + + menu.add("sub:align"); + for (var n=0; n 0; + } + + + JSROOT.TObjectPainter.prototype.FindInPrimitives = function(objname) { + // try to find object by name in list of pad primitives + // used to find title drawing + + var painter = this.pad_painter(true); + if ((painter === null) || (painter.pad === null)) return null; + + if (painter.pad.fPrimitives !== null) + for (var n=0;n draw_g.property('text_factor'))) draw_g.property('text_factor', value); + } + + JSROOT.TObjectPainter.prototype.GetBoundarySizes = function(elem) { + // getBBox does not work in mozilla when object is not displayed or not visisble :( + // getBoundingClientRect() returns wrong sizes for MathJax + // are there good solution? + + if (elem===null) { console.warn('empty node in GetBoundarySizes'); return { width:0, height:0 }; } + var box = elem.getBoundingClientRect(); // works always, but returns sometimes wrong results + if (parseInt(box.width) > 0) box = elem.getBBox(); // check that elements visible, request precise value + var res = { width : parseInt(box.width), height : parseInt(box.height) }; + if ('left' in box) { res.x = parseInt(box.left); res.y = parseInt(box.right); } else + if ('x' in box) { res.x = parseInt(box.x); res.y = parseInt(box.y); } + return res; + } + + JSROOT.TObjectPainter.prototype.FinishTextDrawing = function(draw_g, call_ready) { + if (!draw_g) draw_g = this.draw_g; + var pthis = this; + + var svgs = null; + + if (draw_g.property('mathjax_use')) { + draw_g.property('mathjax_use', false); + + var missing = false; + svgs = draw_g.selectAll(".math_svg"); + + svgs.each(function() { + var fo_g = d3.select(this); + if (fo_g.node().parentNode !== draw_g.node()) return; + var entry = fo_g.property('_element'); + if (d3.select(entry).select("svg").empty()) missing = true; + }); + + // is any svg missing we should wait until drawing is really finished + if (missing) { + JSROOT.AssertPrerequisites('mathjax', function() { + if (typeof MathJax == 'object') + MathJax.Hub.Queue(["FinishTextDrawing", pthis, draw_g, call_ready]); + }); + return null; + } + } + + if (svgs==null) svgs = draw_g.selectAll(".math_svg"); + + var painter = this, svg_factor = 0.; + + // adjust font size (if there are normal text) + var f = draw_g.property('text_factor'); + if ((f>0) && ((f<0.9) || (f>1.))) { + var font = draw_g.property('text_font'); + font.size = Math.floor(font.size/f); + if (draw_g.property('max_font_size') && (font.size>draw_g.property('max_font_size'))) + font.size = draw_g.property('max_font_size'); + draw_g.call(font.func); + } + + // first remove dummy divs and check scaling coefficient + svgs.each(function() { + var fo_g = d3.select(this); + if (fo_g.node().parentNode !== draw_g.node()) return; + var entry = fo_g.property('_element'), + rotate = fo_g.property('_rotate'); + + fo_g.property('_element', null); + + var vvv = d3.select(entry).select("svg"); + if (vvv.empty()) { + JSROOT.console('MathJax SVG ouptut error'); + return; + } + + vvv.remove(); + document.body.removeChild(entry); + + fo_g.append(function() { return vvv.node(); }); + + if (fo_g.property('_scale')) { + var box = painter.GetBoundarySizes(fo_g.node()); + svg_factor = Math.max(svg_factor, 1.05*box.width / fo_g.property('_width'), + 1.05*box.height / fo_g.property('_height')); + } + }); + + svgs.each(function() { + var fo_g = d3.select(this); + // only direct parent + if (fo_g.node().parentNode !== draw_g.node()) return; + + if (svg_factor > 0.) { + var m = fo_g.select("svg"); // MathJax svg + var mw = m.attr("width"), mh = m.attr("height"); + if ((typeof mw == 'string') && (typeof mh == 'string') && (mw.indexOf("ex") > 0) && (mh.indexOf("ex") > 0)) { + mw = parseFloat(mw.substr(0,mw.length-2)); + mh = parseFloat(mh.substr(0,mh.length-2)); + if ((mw>0) && (mh>0)) { + m.attr("width", (mw/svg_factor).toFixed(2)+"ex"); + m.attr("height", (mh/svg_factor).toFixed(2)+"ex"); + } + } else { + JSROOT.console('Fail to downscale MathJax output'); + } + } + + var box = painter.GetBoundarySizes(fo_g.node()), // sizes before rotation + align = fo_g.property('_align'), + rotate = fo_g.property('_rotate'), + fo_w = fo_g.property('_width'), + fo_h = fo_g.property('_height'), + tr = { x: fo_g.property('_x'), y: fo_g.property('_y') }; + + var sign = { x:1, y:1 }, nx = "x", ny = "y"; + if (rotate == 180) { sign.x = sign.y = -1; } else + if ((rotate == 270) || (rotate == 90)) { + sign.x = (rotate===270) ? -1 : 1; + sign.y = -sign.x; + nx = "y"; ny = "x"; // replace names to which align applied + } + + if (!fo_g.property('_scale')) fo_w = fo_h = 0; + + if (align[0] == 'middle') tr[nx] += sign.x*(fo_w - box.width)/2; else + if (align[0] == 'end') tr[nx] += sign.x*(fo_w - box.width); + + if (align[1] == 'middle') tr[ny] += sign.y*(fo_h - box.height)/2; else + if (align[1] == 'bottom') tr[ny] += sign.y*(fo_h - box.height); + + var trans = "translate("+tr.x+","+tr.y+")"; + if (rotate!==0) trans += " rotate("+rotate+",0,0)"; + + fo_g.attr('transform', trans).attr('visibility', null); + }); + + // now hidden text after rescaling can be shown + draw_g.selectAll('.hidden_text').attr('opacity', '1').classed('hidden_text',false); + + // if specified, call ready function + JSROOT.CallBack(call_ready); + + return draw_g.property('max_text_width'); + } + + JSROOT.TObjectPainter.prototype.DrawText = function(align_arg, x, y, w, h, label, tcolor, latex_kind, draw_g) { + + if (!draw_g) draw_g = this.draw_g; + var align; + + if (typeof align_arg == 'string') { + align = align_arg.split(";"); + if (align.length==1) align.push('middle'); + } else { + align = ['start', 'middle']; + if ((align_arg / 10) >= 3) align[0] = 'end'; else + if ((align_arg / 10) >= 2) align[0] = 'middle'; + if ((align_arg % 10) == 0) align[1] = 'bottom'; else + if ((align_arg % 10) == 1) align[1] = 'bottom'; else + if ((align_arg % 10) == 3) align[1] = 'top'; + } + + var scale = (w>0) && (h>0); + + if (latex_kind==null) latex_kind = 1; + if (latex_kind<2) + if (!JSROOT.Painter.isAnyLatex(label)) latex_kind = 0; + + var use_normal_text = ((JSROOT.gStyle.MathJax<1) && (latex_kind!==2)) || (latex_kind<1); + + // only Firefox can correctly rotate incapsulated SVG, produced by MathJax + // if (!use_normal_text && (h<0) && !JSROOT.browser.isFirefox) use_normal_text = true; + + if (use_normal_text) { + if (latex_kind>0) label = JSROOT.Painter.translateLaTeX(label); + + var pos_x = x.toFixed(1), pos_y = y.toFixed(1), pos_dy = null, middleline = false; + + if (w>0) { + // adjust x position when scale into specified rectangle + if (align[0]=="middle") pos_x = (x+w*0.5).toFixed(1); else + if (align[0]=="end") pos_x = (x+w).toFixed(1); + } + + if (h>0) { + if (align[1] == 'bottom') pos_y = (y + h).toFixed(1); else + if (align[1] == 'top') pos_dy = ".8em"; else { + pos_y = (y + h/2).toFixed(1); + if (JSROOT.browser.isIE) pos_dy = ".4em"; else middleline = true; + } + } else { + if (align[1] == 'top') pos_dy = ".8em"; else + if (align[1] == 'middle') { + if (JSROOT.browser.isIE) pos_dy = ".4em"; else middleline = true; + } + } + + // use translate and then rotate to avoid complex sign calculations + var trans = "translate("+pos_x+","+pos_y+")"; + if (!scale && (h<0)) trans += " rotate("+(-h)+",0,0)"; + + var txt = draw_g.append("text") + .attr("text-anchor", align[0]) + .attr("x", 0) + .attr("y", 0) + .attr("fill", tcolor ? tcolor : null) + .attr("transform", trans) + .text(label) + if (pos_dy!=null) txt.attr("dy", pos_dy); + if (middleline) txt.attr("dominant-baseline", "middle"); + + var box = this.GetBoundarySizes(txt.node()); + + if (scale) txt.classed('hidden_text',true).attr('opacity','0'); // hide rescale elements + + if (box.width > draw_g.property('max_text_width')) draw_g.property('max_text_width', box.width); + if ((w>0) && scale) this.TextScaleFactor(1.05*box.width / w, draw_g); + if ((h>0) && scale) this.TextScaleFactor(1.*box.height / h, draw_g); + + return box.width; + } + + w = Math.round(w); h = Math.round(h); + x = Math.round(x); y = Math.round(y); + + var rotate = 0; + + if (!scale && h<0) { rotate = Math.abs(h); h = 0; } + + var fo_g = draw_g.append("svg:g") + .attr('class', 'math_svg') + .attr('visibility','hidden') + .property('_x',x) // used for translation later + .property('_y',y) + .property('_width',w) // used to check scaling + .property('_height',h) + .property('_scale', scale) + .property('_rotate', rotate) + .property('_align', align); + + var element = document.createElement("div"); + d3.select(element).style("visibility", "hidden") + .style("overflow", "hidden") + .style("position", "absolute") + .html(JSROOT.Painter.translateMath(label, latex_kind, tcolor)); + document.body.appendChild(element); + + draw_g.property('mathjax_use', true); // one need to know that mathjax is used + fo_g.property('_element', element); + + JSROOT.AssertPrerequisites('mathjax', function() { + if (typeof MathJax == 'object') + MathJax.Hub.Queue(["Typeset", MathJax.Hub, element]); + }); + + return 0; + } + + // =========================================================== + + JSROOT.TFramePainter = function(tframe) { + JSROOT.TObjectPainter.call(this, tframe); + this.tooltip_enabled = true; + this.tooltip_allowed = (JSROOT.gStyle.Tooltip > 0); + } + + JSROOT.TFramePainter.prototype = Object.create(JSROOT.TObjectPainter.prototype); + + JSROOT.TFramePainter.prototype.Shrink = function(shrink_left, shrink_right) { + this.fX1NDC += shrink_left; + this.fX2NDC -= shrink_right; + } + + JSROOT.TFramePainter.prototype.UpdateAttributes = function(force) { + var root_pad = this.root_pad(), + tframe = this.GetObject(); + + if ((this.fX1NDC === undefined) || (force && !this.modified_NDC)) { + if (!root_pad) { + JSROOT.extend(this, JSROOT.gStyle.FrameNDC); + } else { + JSROOT.extend(this, { + fX1NDC: root_pad.fLeftMargin, + fX2NDC: 1 - root_pad.fRightMargin, + fY1NDC: root_pad.fBottomMargin, + fY2NDC: 1 - root_pad.fTopMargin + }); + } + } + + if (this.fillatt === undefined) { + if (tframe) + this.fillatt = this.createAttFill(tframe); + else + if (root_pad) + this.fillatt = this.createAttFill(null, root_pad.fFrameFillStyle, root_pad.fFrameFillColor); + else + this.fillatt = this.createAttFill(null, 1001, 0); + + // force white color for the frame + if (this.fillatt.color == 'none') this.fillatt.color = 'white'; + } + + if (this.lineatt === undefined) + this.lineatt = JSROOT.Painter.createAttLine(tframe ? tframe : 'black'); + } + + JSROOT.TFramePainter.prototype.Redraw = function() { + + // first update all attributes from objects + this.UpdateAttributes(); + + var width = this.pad_width(), + height = this.pad_height(), + lm = Math.round(width * this.fX1NDC), + w = Math.round(width * (this.fX2NDC - this.fX1NDC)), + tm = Math.round(height * (1 - this.fY2NDC)), + h = Math.round(height * (this.fY2NDC - this.fY1NDC)); + + // this is svg:g object - container for every other items belonging to frame + this.draw_g = this.svg_frame(); + if (this.draw_g.empty()) + return console.error('did not found frame layer'); + + var top_rect = this.draw_g.select("rect"), + main_svg = this.draw_g.select(".main_layer"); + + if (main_svg.empty()) { + this.draw_g.append("svg:title").text(""); + + top_rect = this.draw_g.append("svg:rect"); + + // append for the moment three layers - for drawing and axis + this.draw_g.append('svg:g').attr('class','grid_layer'); + + main_svg = this.draw_g.append('svg:svg') + .attr('class','main_layer') + .attr("x", 0) + .attr("y", 0) + .attr('overflow', 'hidden'); + + this.draw_g.append('svg:g').attr('class','axis_layer'); + this.draw_g.append('svg:g').attr('class','upper_layer'); + } + + // simple way to access painter via frame container + this.draw_g.property('frame_painter', this); + + this.draw_g.attr("x", lm) + .attr("y", tm) + .attr("width", w) + .attr("height", h) + .property('draw_x', lm) + .property('draw_y', tm) + .property('draw_width', w) + .property('draw_height', h) + .attr("transform", "translate(" + lm + "," + tm + ")"); + + top_rect.attr("x", 0) + .attr("y", 0) + .attr("width", w) + .attr("height", h) + .call(this.fillatt.func) + .call(this.lineatt.func); + + main_svg.attr("width", w) + .attr("height", h) + .attr("viewBox", "0 0 " + w + " " + h); + + this.AddDrag({ obj: this, only_resize: true, minwidth: 20, minheight: 20, + redraw: this.RedrawPad.bind(this) }); + + var tooltip_rect = this.draw_g.select(".interactive_rect"); + + if (JSROOT.gStyle.Tooltip === 0) + return tooltip_rect.remove(); + + var painter = this; + + function MouseMoveEvent() { + var pnt = d3.mouse(tooltip_rect.node()); + painter.ProcessTooltipEvent({ x: pnt[0], y: pnt[1], touch: false }); + } + + function MouseCloseEvent() { + painter.ProcessTooltipEvent(null); + } + + function TouchMoveEvent() { + var pnt = d3.touches(tooltip_rect.node()); + if (!pnt || pnt.length !== 1) return painter.ProcessTooltipEvent(null); + painter.ProcessTooltipEvent({ x: pnt[0][0], y: pnt[0][1], touch: true }); + } + + function TouchCloseEvent() { + painter.ProcessTooltipEvent(null); + } + + if (tooltip_rect.empty()) { + tooltip_rect = + this.draw_g + .append("rect") + .attr("class","interactive_rect") + .style("opacity","0") + .style("fill","none") + .style("pointer-events", "visibleFill") + .on('mouseenter', MouseMoveEvent) + .on('mousemove', MouseMoveEvent) + .on('mouseleave', MouseCloseEvent); + + if (JSROOT.touches) + tooltip_rect.on("touchstart", TouchMoveEvent) + .on("touchmove", TouchMoveEvent) + .on("touchend", TouchCloseEvent) + .on("touchcancel", TouchCloseEvent); + } + + tooltip_rect.attr("x", 0) + .attr("y", 0) + .attr("width", w) + .attr("height", h); + + var hintsg = this.svg_layer("stat_layer").select(".objects_hints"); + // if tooltips were visible before, try to reconstruct them after short timeout + if (!hintsg.empty() && (JSROOT.gStyle.Tooltip > 0)) + setTimeout(this.ProcessTooltipEvent.bind(this, hintsg.property('last_point')), 10); + } + + + JSROOT.TFramePainter.prototype.FillContextMenu = function(menu) { + // fill context menu for the frame + // it could be appended to the histogram menus + + var main = this.main_painter(), alone = menu.size()==0, pad = this.root_pad(); + + if (alone) + menu.add("header:Frame"); + else + menu.add("separator"); + + if (main) { + if (main.zoom_xmin !== main.zoom_xmax) + menu.add("Unzoom X", main.Unzoom.bind(main,"x")); + if (main.zoom_ymin !== main.zoom_ymax) + menu.add("Unzoom Y", main.Unzoom.bind(main,"y")); + if (main.zoom_zmin !== main.zoom_zmax) + menu.add("Unzoom Z", main.Unzoom.bind(main,"z")); + menu.add("Unzoom all", main.Unzoom.bind(main,"xyz")); + + if (pad) { + menu.addchk(pad.fLogx, "SetLogx", main.ToggleLog.bind(main,"x")); + + menu.addchk(pad.fLogy, "SetLogy", main.ToggleLog.bind(main,"y")); + + if (main.Dimension() == 2) + menu.addchk(pad.fLogz, "SetLogz", main.ToggleLog.bind(main,"z")); + } + menu.add("separator"); + } + + menu.addchk(this.tooltip_allowed, "Show tooltips", function() { + var fp = this.frame_painter(); + if (fp) fp.tooltip_allowed = !fp.tooltip_allowed; + }); + this.FillAttContextMenu(menu,alone ? "" : "Frame "); + menu.add("separator"); + menu.add("Save as frame.png", function(arg) { + var top = this.svg_frame(); + if (!top.empty()) + JSROOT.AssertPrerequisites("savepng", function() { + saveSvgAsPng(top.node(), "frame.png"); + }); + }); + + return true; + } + + + JSROOT.TFramePainter.prototype.IsTooltipShown = function() { + // return true if tooltip is shown, use to prevent some other action + if (JSROOT.gStyle.Tooltip < 1) return false; + return ! (this.svg_layer("stat_layer").select(".objects_hints").empty()); + } + + JSROOT.TFramePainter.prototype.ProcessTooltipEvent = function(pnt, enabled) { + + if (enabled !== undefined) this.tooltip_enabled = enabled; + + if ((pnt === undefined) || !this.tooltip_allowed || !this.tooltip_enabled) pnt = null; + + var hints = [], nhints = 0, maxlen = 0, lastcolor1 = 0, usecolor1 = false, + textheight = 11, hmargin = 3, wmargin = 3, hstep = 1.2, + height = this.frame_height(), + width = this.frame_width(), + pp = this.pad_painter(true), + maxhinty = this.pad_height() - this.draw_g.property('draw_y'), + font = JSROOT.Painter.getFontDetails(160, textheight); + + // collect tooltips from pad painter - it has list of all drawn objects + if (pp!==null) hints = pp.GetTooltips(pnt); + + if (pnt && pnt.touch) textheight = 15; + + for (var n=0; n < hints.length; ++n) { + var hint = hints[n]; + if (!hint) continue; + + nhints++; + + for (var l=0;l 1) { + // if there are many hints, place them left or right + + var bleft = 0.5, bright = 0.5; + + if (viewmode=="left") bright = 0.7; else + if (viewmode=="right") bleft = 0.3; + + if (pnt.x <= bleft*width) { + viewmode = "left"; + posx = 20; + } else + if (pnt.x >= bright*width) { + viewmode = "right"; + posx = width - 60; + } else { + posx = hintsg.property('startx'); + } + } else { + viewmode = "single"; + } + + if (viewmode !== hintsg.property('viewmode')) { + hintsg.property('viewmode', viewmode); + hintsg.selectAll("*").remove(); + } + + var curry = 10, // normal y coordiante + gapy = 10, // y coordiante, taking into account all gaps + gapminx = -1111, gapmaxx = -1111; + + function FindPosInGap(y) { + for (var n=0;(n=y-5) && (hint.y <= y+hint.height+5)) { + y = hint.y+10; + n = -1; + } + } + return y; + } + + for (var n=0; n < hints.length; ++n) { + var hint = hints[n]; + var group = hintsg.select(".painter_hint_"+n); + if (hint===null) { + group.remove(); + continue; + } + + var was_empty = group.empty(); + + if (was_empty) + group = hintsg.append("svg:svg") + .attr("class", "painter_hint_"+n) + .style('overflow','hidden') + .attr("opacity","0") + .style("pointer-events","none"); + + if (viewmode == "single") { + curry = pnt.touch ? (pnt.y - hint.height - 5) : Math.min(pnt.y + 15, maxhinty - hint.height - 3); + } else { + gapy = FindPosInGap(gapy); + if ((gapminx === -1111) && (gapmaxx === -1111)) gapminx = gapmaxx = hint.x; + gapminx = Math.min(gapminx, hint.x); + gapmaxx = Math.min(gapmaxx, hint.x); + } + + group.attr("x", posx) + .attr("y", curry) + .property("gapy", gapy); + + curry += hint.height + 5; + gapy += hint.height + 5; + + if (!was_empty) + group.selectAll("*").remove(); + + group.attr("width", 60) + .attr("height", hint.height); + + var r = group.append("rect") + .attr("x",0) + .attr("y",0) + .attr("width", 60) + .attr("height", hint.height) + .attr("fill","lightgrey") + .style("pointer-events","none"); + + if (nhints > 1) { + var col = usecolor1 ? hint.color1 : hint.color2; + if ((col !== undefined) && (col!=='none')) + r.attr("stroke", col).attr("stroke-width", hint.exact ? 3 : 1); + } + + if (hint.lines != null) { + for (var l=0;l width - 20)) { + posx = width - actualw - 20; + svgs.attr("x", posx); + } + + // if gap not very big, apply gapy coordinate to open view on the histogram + if ((viewmode !== "single") && (gapy < maxhinty) && (gapy !== curry)) + if ((gapminx <= posx+actualw+5) && (gapmaxx >= posx-5)) + svgs.attr("y", function() { return d3.select(this).property('gapy'); }); + + if (actualw > 10) + svgs.attr("width", actualw) + .select('rect').attr("width", actualw); + + hintsg.property('startx', posx); + } + + JSROOT.Painter.drawFrame = function(divid, obj) { + var p = new JSROOT.TFramePainter(obj); + p.SetDivId(divid, 2); + p.Redraw(); + return p.DrawingReady(); + } + + // ============================================================ + + // base class for all objects, derived from TPave + JSROOT.TPavePainter = function(pave) { + JSROOT.TObjectPainter.call(this, pave); + this.Enabled = true; + this.UseContextMenu = true; + this.UseTextColor = false; // indicates if text color used, enabled menu entry + } + + JSROOT.TPavePainter.prototype = Object.create(JSROOT.TObjectPainter.prototype); + + JSROOT.TPavePainter.prototype.DrawPave = function(arg) { + // this draw only basic TPave + + this.UseTextColor = false; + + if (!this.Enabled) + return this.RemoveDrawG(); + + var pt = this.GetObject(); + + if (pt.fInit===0) { + pt.fInit = 1; + var pad = this.root_pad(); + if (pt.fOption.indexOf("NDC")>=0) { + pt.fX1NDC = pt.fX1; pt.fX2NDC = pt.fX2; + pt.fY1NDC = pt.fY1; pt.fY2NDC = pt.fY2; + } else + if (pad !== null) { + if (pad.fLogx) { + if (pt.fX1 > 0) pt.fX1 = JSROOT.log10(pt.fX1); + if (pt.fX2 > 0) pt.fX2 = JSROOT.log10(pt.fX2); + } + if (pad.fLogy) { + if (pt.fY1 > 0) pt.fY1 = JSROOT.log10(pt.fY1); + if (pt.fY2 > 0) pt.fY2 = JSROOT.log10(pt.fY2); + } + pt.fX1NDC = (pt.fX1-pad.fX1) / (pad.fX2 - pad.fX1); + pt.fY1NDC = (pt.fY1-pad.fY1) / (pad.fY2 - pad.fY1); + pt.fX2NDC = (pt.fX2-pad.fX1) / (pad.fX2 - pad.fX1); + pt.fY2NDC = (pt.fY2-pad.fY1) / (pad.fY2 - pad.fY1); + } else { + pt.fX1NDC = pt.fY1NDC = 0.1; + pt.fX2NDC = pt.fY2NDC = 0.9; + } + } + + var pos_x = Math.round(pt.fX1NDC * this.pad_width()), + pos_y = Math.round((1.0 - pt.fY2NDC) * this.pad_height()), + width = Math.round((pt.fX2NDC - pt.fX1NDC) * this.pad_width()), + height = Math.round((pt.fY2NDC - pt.fY1NDC) * this.pad_height()), + lwidth = pt.fBorderSize; + + // container used to recalculate coordinates + this.RecreateDrawG(true, this.IsStats() ? "stat_layer" : "text_layer"); + + // position and size required only for drag functions + this.draw_g + .attr("x", pos_x) + .attr("y", pos_y) + .attr("width", width) + .attr("height", height) + .attr("transform", "translate(" + pos_x + "," + pos_y + ")"); + + // add shadow decoration before main rect + if ((lwidth > 1) && (pt.fShadowColor > 0)) + this.draw_g.append("svg:path") + .attr("d","M" + width + "," + height + + " v" + (-height + lwidth) + " h" + lwidth + + " v" + height + " h" + (-width) + + " v" + (-lwidth) + " Z") + .style("fill", JSROOT.Painter.root_colors[pt.fShadowColor]) + .style("stroke", JSROOT.Painter.root_colors[pt.fShadowColor]) + .style("stroke-width", "1px"); + + if (this.lineatt === undefined) + this.lineatt = JSROOT.Painter.createAttLine(pt, lwidth>0 ? 1 : 0); + if (this.fillatt === undefined) + this.fillatt = this.createAttFill(pt); + + this.draw_g.append("rect") + .attr("x", 0) + .attr("y", 0) + .attr("width", width) + .attr("height", height) + .style("pointer-events", "visibleFill") + .call(this.fillatt.func) + .call(this.lineatt.func); + + if ('PaveDrawFunc' in this) + this.PaveDrawFunc(width, height, arg); + + this.AddDrag({ obj: pt, minwidth: 10, minheight: 20, + redraw: this.DrawPave.bind(this), + ctxmenu: JSROOT.touches && JSROOT.gStyle.ContextMenu && this.UseContextMenu }); + + if (this.UseContextMenu && JSROOT.gStyle.ContextMenu) + this.draw_g.on("contextmenu", this.ShowContextMenu.bind(this) ); + } + + JSROOT.TPavePainter.prototype.DrawPaveLabel = function(width, height) { + this.UseTextColor = true; + + var pave = this.GetObject(); + + this.StartTextDrawing(pave.fTextFont, height/1.2); + + this.DrawText(pave.fTextAlign, 0, 0, width, height, pave.fLabel, JSROOT.Painter.root_colors[pave.fTextColor]); + + this.FinishTextDrawing(); + } + + JSROOT.TPavePainter.prototype.DrawPaveText = function(width, height, refill) { + + if (refill && this.IsStats()) this.FillStatistic(); + + var pt = this.GetObject(), + tcolor = JSROOT.Painter.root_colors[pt.fTextColor], + lwidth = pt.fBorderSize, + first_stat = 0, + num_cols = 0, + nlines = pt.fLines.arr.length, + lines = [], + maxlen = 0; + + // adjust font size + for (var j = 0; j < nlines; ++j) { + var line = pt.fLines.arr[j].fTitle; + lines.push(line); + if (j>0) maxlen = Math.max(maxlen, line.length); + if (!this.IsStats() || (j == 0) || (line.indexOf('|') < 0)) continue; + if (first_stat === 0) first_stat = j; + var parts = line.split("|"); + if (parts.length > num_cols) + num_cols = parts.length; + } + + // for characters like 'p' or 'y' several more pixels required to stay in the box when drawn in last line + var stepy = height / nlines, has_head = false, margin_x = pt.fMargin * width; + + this.StartTextDrawing(pt.fTextFont, height/(nlines * 1.2)); + + if (nlines == 1) { + this.DrawText(pt.fTextAlign, 0, 0, width, height, lines[0], tcolor); + this.UseTextColor = true; + } else { + for (var j = 0; j < nlines; ++j) { + var posy = j*stepy, + jcolor = JSROOT.Painter.root_colors[pt.fLines.arr[j].fTextColor]; + if ((pt.fLines.arr[j].fTextColor == 0) || (jcolor===undefined)) { + jcolor = tcolor; + this.UseTextColor = true; + } + + if (this.IsStats()) { + if ((first_stat > 0) && (j >= first_stat)) { + var parts = lines[j].split("|"); + for (var n = 0; n < parts.length; ++n) + this.DrawText("middle", + width * n / num_cols, posy, + width/num_cols, stepy, parts[n], jcolor); + } else if (lines[j].indexOf('=') < 0) { + if (j==0) { + has_head = true; + if (lines[j].length > maxlen + 5) + lines[j] = lines[j].substr(0,maxlen+2) + "..."; + } + this.DrawText((j == 0) ? "middle" : "start", + margin_x, posy, width-2*margin_x, stepy, lines[j], jcolor); + } else { + var parts = lines[j].split("="), sumw = 0; + for (var n = 0; n < 2; ++n) + sumw += this.DrawText((n == 0) ? "start" : "end", + margin_x, posy, width-2*margin_x, stepy, parts[n], jcolor); + this.TextScaleFactor(1.05*sumw/(width-2*margin_x), this.draw_g); + } + } else { + this.DrawText(pt.fTextAlign, margin_x, posy, width-2*margin_x, stepy, lines[j], jcolor); + } + } + } + + var maxtw = this.FinishTextDrawing(); + + if ((lwidth > 0) && has_head) { + this.draw_g.append("svg:line") + .attr("x1", 0) + .attr("y1", stepy.toFixed(1)) + .attr("x2", width) + .attr("y2", stepy.toFixed(1)) + .call(this.lineatt.func); + } + + if ((first_stat > 0) && (num_cols > 1)) { + for (var nrow = first_stat; nrow < nlines; ++nrow) + this.draw_g.append("svg:line") + .attr("x1", 0) + .attr("y1", (nrow * stepy).toFixed(1)) + .attr("x2", width) + .attr("y2", (nrow * stepy).toFixed(1)) + .call(this.lineatt.func); + + for (var ncol = 0; ncol < num_cols - 1; ++ncol) + this.draw_g.append("svg:line") + .attr("x1", (width / num_cols * (ncol + 1)).toFixed(1)) + .attr("y1", (first_stat * stepy).toFixed(1)) + .attr("x2", (width / num_cols * (ncol + 1)).toFixed(1)) + .attr("y2", height) + .call(this.lineatt.func); + } + + if ((pt.fLabel.length>0) && !this.IsStats()) { + var x = Math.round(width*0.25), + y = Math.round(-height*0.02), + w = Math.round(width*0.5), + h = Math.round(height*0.04); + + var lbl_g = this.draw_g.append("svg:g"); + + lbl_g.append("rect") + .attr("x", x) + .attr("y", y) + .attr("width", w) + .attr("height", h) + .call(this.fillatt.func) + .call(this.lineatt.func); + + this.StartTextDrawing(pt.fTextFont, h/1.5, lbl_g); + + this.DrawText(22, x, y, w, h, pt.fLabel, tcolor, 1, lbl_g); + + this.FinishTextDrawing(lbl_g); + + this.UseTextColor = true; + } + } + + JSROOT.TPavePainter.prototype.Format = function(value, fmt) { + // method used to convert value to string according specified format + // format can be like 5.4g or 4.2e or 6.4f + if (!fmt) fmt = "stat"; + + var pave = this.GetObject(); + + if (fmt=="stat") { + fmt = pave.fStatFormat; + if (!fmt) fmt = JSROOT.gStyle.StatFormat; + } else + if (fmt=="fit") { + fmt = pave.fFitFormat; + if (!fmt) fmt = JSROOT.gStyle.FitFormat; + } else + if (fmt=="entries") { + if (value < 1e9) return value.toFixed(0); + fmt = "14.7g"; + } else + if (fmt=="last") { + fmt = this.lastformat; + } + + delete this.lastformat; + + if (!fmt) fmt = "6.4g"; + + var res = JSROOT.FFormat(value, fmt); + + this.lastformat = JSROOT.lastFFormat; + + return res; + } + + JSROOT.TPavePainter.prototype.ShowContextMenu = function(evnt) { + if (!evnt) { + d3.event.stopPropagation(); // disable main context menu + d3.event.preventDefault(); // disable browser context menu + + // one need to copy event, while after call back event may be changed + evnt = d3.event; + } + + var pthis = this, pave = this.GetObject(); + + JSROOT.Painter.createMenu(function(menu) { + menu.painter = pthis; // set as this in callbacks + menu.add("header: " + pave._typename + "::" + pave.fName); + if (pthis.IsStats()) { + + menu.add("SetStatFormat", function() { + var fmt = prompt("Enter StatFormat", pave.fStatFormat); + if (fmt!=null) { + pave.fStatFormat = fmt; + pthis.Redraw(); + } + }); + menu.add("SetFitFormat", function() { + var fmt = prompt("Enter FitFormat", pave.fFitFormat); + if (fmt!=null) { + pave.fFitFormat = fmt; + pthis.Redraw(); + } + }); + menu.add("separator"); + menu.add("sub:SetOptStat", function() { + // todo - use jqury dialog here + var fmt = prompt("Enter OptStat", pave.fOptStat); + if (fmt!=null) { pave.fOptStat = parseInt(fmt); pthis.Redraw(); } + }); + function AddStatOpt(pos, name) { + var opt = (pos<10) ? pave.fOptStat : pave.fOptFit; + opt = parseInt(parseInt(opt) / parseInt(Math.pow(10,pos % 10))) % 10; + menu.addchk(opt, name, opt * 100 + pos, function(arg) { + var newopt = (arg % 100 < 10) ? pave.fOptStat : pave.fOptFit; + var oldopt = parseInt(arg / 100); + newopt -= (oldopt>0 ? oldopt : -1) * parseInt(Math.pow(10, arg % 10)); + if (arg % 100 < 10) pave.fOptStat = newopt; + else pave.fOptFit = newopt; + pthis.Redraw(); + }); + } + + AddStatOpt(0, "Histogram name"); + AddStatOpt(1, "Entries"); + AddStatOpt(2, "Mean"); + AddStatOpt(3, "Std Dev"); + AddStatOpt(4, "Underflow"); + AddStatOpt(5, "Overflow"); + AddStatOpt(6, "Integral"); + AddStatOpt(7, "Skewness"); + AddStatOpt(8, "Kurtosis"); + menu.add("endsub:"); + + menu.add("sub:SetOptFit", function() { + // todo - use jqury dialog here + var fmt = prompt("Enter OptStat", pave.fOptFit); + if (fmt!=null) { pave.fOptFit = parseInt(fmt); pthis.Redraw(); } + }); + AddStatOpt(10, "Fit parameters"); + AddStatOpt(11, "Par errors"); + AddStatOpt(12, "Chi square / NDF"); + AddStatOpt(13, "Probability"); + menu.add("endsub:"); + + menu.add("separator"); + } + + if (pthis.UseTextColor) + pthis.TextAttContextMenu(menu); + + pthis.FillAttContextMenu(menu); + + menu.show(evnt); + }); // end menu creation + } + + JSROOT.TPavePainter.prototype.IsStats = function() { + return this.MatchObjectType('TPaveStats'); + } + + JSROOT.TPavePainter.prototype.FillStatistic = function() { + var pave = this.GetObject(), main = this.main_painter(); + + if (pave.fName !== "stats") return false; + if ((main===null) || !('FillStatistic' in main)) return false; + + // no need to refill statistic if histogram is dummy + if (main.IsDummyHisto()) return true; + + var dostat = new Number(pave.fOptStat); + var dofit = new Number(pave.fOptFit); + if (!dostat) dostat = JSROOT.gStyle.OptStat; + if (!dofit) dofit = JSROOT.gStyle.OptFit; + + // make empty at the beginning + pave.Clear(); + + // we take statistic from first painter + main.FillStatistic(this, dostat, dofit); + + return true; + } + + JSROOT.TPavePainter.prototype.UpdateObject = function(obj) { + if (!this.MatchObjectType(obj)) return false; + + var pave = this.GetObject(); + + if (!('modified_NDC' in pave)) { + // if position was not modified interactively, update from source object + pave.fInit = obj.fInit; + pave.fX1 = obj.fX1; pave.fX2 = obj.fX2; + pave.fY1 = obj.fY1; pave.fY2 = obj.fY2; + pave.fX1NDC = obj.fX1NDC; pave.fX2NDC = obj.fX2NDC; + pave.fY1NDC = obj.fY1NDC; pave.fY2NDC = obj.fY2NDC; + } + + if (obj._typename === 'TPaveText') { + pave.fLines = JSROOT.clone(obj.fLines); + return true; + } else + if (obj._typename === 'TPaveLabel') { + pave.fLabel = obj.fLabel; + return true; + } else + if (obj._typename === 'TPaveStats') { + pave.fOptStat = obj.fOptStat; + pave.fOptFit = obj.fOptFit; + return true; + } + + return false; + } + + JSROOT.TPavePainter.prototype.Redraw = function() { + // if pavetext artificially disabled, do not redraw it + + this.DrawPave(true); + } + + JSROOT.Painter.drawPaveText = function(divid, pave, opt) { + + // one could force drawing of PaveText on specific sub-pad + var onpad = ((typeof opt == 'string') && (opt.indexOf("onpad:")==0)) ? opt.substr(6) : undefined; + + var painter = new JSROOT.TPavePainter(pave); + painter.SetDivId(divid, 2, onpad); + + switch (pave._typename) { + case "TPaveLabel": + painter.PaveDrawFunc = painter.DrawPaveLabel; + break; + case "TPaveStats": + case "TPaveText": + painter.PaveDrawFunc = painter.DrawPaveText; + break; + } + + painter.Redraw(); + + return painter.DrawingReady(); + } + + // =========================================================================== + + JSROOT.TPadPainter = function(pad, iscan) { + JSROOT.TObjectPainter.call(this, pad); + this.pad = pad; + this.iscan = iscan; // indicate if workign with canvas + this.this_pad_name = ""; + if (!this.iscan && (pad !== null) && ('fName' in pad)) + this.this_pad_name = pad.fName.replace(" ", "_"); // avoid empty symbol in pad name + this.painters = new Array; // complete list of all painters in the pad + this.has_canvas = true; + } + + JSROOT.TPadPainter.prototype = Object.create(JSROOT.TObjectPainter.prototype); + + JSROOT.TPadPainter.prototype.ButtonSize = function(fact) { + return Math.round((!fact ? 1 : fact) * (this.iscan || !this.has_canvas ? 16 : 12)); + } + + JSROOT.TPadPainter.prototype.CreateCanvasSvg = function(check_resize, new_size) { + + var render_to = this.select_main(); + + var rect = this.main_visible_rect(); + + // this is size where canvas should be rendered + var w = rect.width, h = rect.height; + + if ((typeof new_size == 'object') && (new_size!==null) && ('width' in new_size) && ('height' in new_size)) { + w = new_size.width; + h = new_size.height; + } + + var factor = null, svg = null; + + if (check_resize > 0) { + + svg = this.svg_canvas(); + + var oldw = svg.property('draw_width'), oldh = svg.property('draw_height'); + + if ((w<=0) && (h<=0)) { + svg.attr("visibility", "hidden"); + return false; + } else { + svg.attr("visibility", "visible"); + svg.select(".canvas_fillrect") + .call(this.fillatt.func); + } + + if (check_resize == 1) { + if ((oldw == w) && (oldh == h)) return false; + } + + factor = svg.property('height_factor'); + + if (factor != null) { + // if canvas was resize when created, resize height also now + h = Math.round(w * factor); + render_to.style('height', h+'px'); + } + + if ((check_resize==1) && (oldw>0) && (oldh>0) && !svg.property('redraw_by_resize')) + if ((w/oldw>0.66) && (w/oldw<1.5) && (h/oldh>0.66) && (h/oldh<1.5)) { + // not significant change in actual sizes, keep as it is + // let browser scale SVG without our help + return false; + } + + } else { + + if ((h < 10) && (w > 0)) { + // set aspect ratio for the place, where object will be drawn + + factor = 0.66; + + // for TCanvas reconstruct ratio between width and height + if ((this.pad!==null) && ('fCw' in this.pad) && ('fCh' in this.pad) && (this.pad.fCw > 0)) { + factor = this.pad.fCh / this.pad.fCw; + if ((factor < 0.1) || (factor > 10)) + factor = 0.66; + } + + h = Math.round(w * factor); + + render_to.style('height', h+'px'); + } + + svg = this.select_main() + .append("svg") + .attr("class", "jsroot root_canvas") + .property('pad_painter', this) // this is custom property + .property('mainpainter', null) // this is custom property + .property('current_pad', "") // this is custom property + .property('redraw_by_resize', false); // could be enabled to force redraw by each resize + + svg.append("svg:title").text("ROOT canvas"); + svg.append("svg:rect").attr("class","canvas_fillrect") + .attr("x",0).attr("y",0).style("pointer-events", "visibleFill"); + svg.append("svg:g").attr("class","root_frame"); + svg.append("svg:g").attr("class","subpads_layer"); + svg.append("svg:g").attr("class","special_layer"); + svg.append("svg:g").attr("class","text_layer"); + svg.append("svg:g").attr("class","stat_layer"); + svg.append("svg:g").attr("class","btns_layer"); + + if (JSROOT.gStyle.ContextMenu) + svg.select(".canvas_fillrect").on("contextmenu", this.ShowContextMenu.bind(this)); + } + + if (!this.fillatt || !this.fillatt.changed) + this.fillatt = this.createAttFill(this.pad, 1001, 0); + + if ((w<=0) || (h<=0)) { + svg.attr("visibility", "hidden"); + w = 200; h = 100; // just to complete drawing + } else { + svg.attr("visibility", "visible"); + } + + svg.attr("x", 0) + .attr("y", 0) + .attr("width", "100%") + .attr("height", "100%") + .attr("viewBox", "0 0 " + w + " " + h) + .attr("preserveAspectRatio", "none") // we do not preserve relative ratio + .property('height_factor', factor) + .property('draw_x', 0) + .property('draw_y', 0) + .property('draw_width', w) + .property('draw_height', h); + + svg.select(".canvas_fillrect") + .attr("width",w) + .attr("height",h) + .call(this.fillatt.func); + + this.svg_layer("btns_layer").attr("transform","translate(2," + (h-this.ButtonSize(1.25)) + ")"); + + return true; + } + + JSROOT.TPadPainter.prototype.CreatePadSvg = function(only_resize) { + if (!this.has_canvas) + return this.CreateCanvasSvg(only_resize ? 2 : 0); + + var width = this.svg_canvas().property("draw_width"), + height = this.svg_canvas().property("draw_height"), + w = Math.round(this.pad.fAbsWNDC * width), + h = Math.round(this.pad.fAbsHNDC * height), + x = Math.round(this.pad.fAbsXlowNDC * width), + y = Math.round(height - this.pad.fAbsYlowNDC * height) - h; + + var svg_pad = null, svg_rect = null, btns = null; + + if (only_resize) { + svg_pad = this.svg_pad(this.this_pad_name); + svg_rect = svg_pad.select(".root_pad_border"); + btns = this.svg_layer("btns_layer", this.this_pad_name); + } else { + svg_pad = this.svg_canvas().select(".subpads_layer") + .append("g") + .attr("class", "root_pad") + .attr("pad", this.this_pad_name) // set extra attribute to mark pad name + .property('pad_painter', this) // this is custom property + .property('mainpainter', null); // this is custom property + svg_rect = svg_pad.append("svg:rect").attr("class", "root_pad_border"); + svg_pad.append("svg:g").attr("class","root_frame"); + svg_pad.append("svg:g").attr("class","special_layer"); + svg_pad.append("svg:g").attr("class","text_layer"); + svg_pad.append("svg:g").attr("class","stat_layer"); + btns = svg_pad.append("svg:g").attr("class","btns_layer").property('nextx', 0); + + if (JSROOT.gStyle.ContextMenu) + svg_pad.select(".root_pad_border").on("contextmenu", this.ShowContextMenu.bind(this)); + + if (!this.fillatt || !this.fillatt.changed) + this.fillatt = this.createAttFill(this.pad, 1001, 0); + if (!this.lineatt || !this.lineatt.changed) + this.lineatt = JSROOT.Painter.createAttLine(this.pad) + if (this.pad.fBorderMode == 0) this.lineatt.color = 'none'; + } + + svg_pad.attr("transform", "translate(" + x + "," + y + ")") + .property('draw_x', x) // this is to make similar with canvas + .property('draw_y', y) + .property('draw_width', w) + .property('draw_height', h); + + svg_rect.attr("x", 0) + .attr("y", 0) + .attr("width", w) + .attr("height", h) + .call(this.fillatt.func) + .call(this.lineatt.func); + + btns.attr("transform","translate("+ (w- btns.property('nextx') - this.ButtonSize(0.25)) + "," + (h-this.ButtonSize(1.25)) + ")"); + } + + JSROOT.TPadPainter.prototype.CheckColors = function(can) { + if (can==null) return; + + + + for (var i = 0; i < can.fPrimitives.arr.length; ++i) { + var obj = can.fPrimitives.arr[i]; + if (obj==null) continue; + if ((obj._typename=="TObjArray") && (obj.name == "ListOfColors")) { + JSROOT.Painter.adoptRootColors(obj); + can.fPrimitives.arr.splice(i,1); + can.fPrimitives.opt.splice(i,1); + return; + } + } + } + + JSROOT.TPadPainter.prototype.RemovePrimitive = function(obj) { + if ((this.pad===null) || (this.pad.fPrimitives === null)) return; + var indx = this.pad.fPrimitives.arr.indexOf(obj); + if (indx>=0) this.pad.fPrimitives.RemoveAt(indx); + } + + JSROOT.TPadPainter.prototype.FindPrimitive = function(exact_obj, classname, name) { + if ((this.pad===null) || (this.pad.fPrimitives === null)) return null; + + for (var i=0; i < this.pad.fPrimitives.arr.length; i++) { + var obj = this.pad.fPrimitives.arr[i]; + + if ((exact_obj!==null) && (obj !== exact_obj)) continue; + + if ((classname !== undefined) && (classname !== null)) + if (obj._typename !== classname) continue; + + if ((name !== undefined) && (name !== null)) + if (obj.fName !== name) continue; + + return obj; + } + + return null; + } + + JSROOT.TPadPainter.prototype.HasObjectsToDraw = function() { + // return true if any objects beside sub-pads exists in the pad + + if ((this.pad===null) || !this.pad.fPrimitives || (this.pad.fPrimitives.arr.length==0)) return false; + + for (var n=0;n= this.pad.fPrimitives.arr.length)) + return JSROOT.CallBack(callback); + + var pp = JSROOT.draw(this.divid, this.pad.fPrimitives.arr[indx], this.pad.fPrimitives.opt[indx]); + + if (pp === null) return this.DrawPrimitive(indx+1, callback); + + pp._primitive = true; // mark painter as belonging to primitives + pp.WhenReady(this.DrawPrimitive.bind(this, indx+1, callback)); + } + + + JSROOT.TPadPainter.prototype.GetTooltips = function(pnt) { + var painters = [], hints = []; + + // first count - how many processors are there + if (this.painters !== null) + this.painters.forEach(function(obj) { + if ('ProcessTooltip' in obj) painters.push(obj); + }); + + if (pnt) pnt.nproc = painters.length; + + painters.forEach(function(obj) { + var hint = obj.ProcessTooltip(pnt); + hints.push(hint); + if (hint && pnt.painters) hint.painter = obj; + }); + + return hints; + } + + JSROOT.TPadPainter.prototype.FillContextMenu = function(menu) { + + if (this.pad) + menu.add("header: " + this.pad._typename + "::" + this.pad.fName); + else + menu.add("header: Canvas"); + + if (this.iscan) + menu.addchk((JSROOT.gStyle.Tooltip > 0), "Show tooltips", function() { + JSROOT.gStyle.Tooltip = (JSROOT.gStyle.Tooltip === 0) ? 1 : -JSROOT.gStyle.Tooltip; + }); + + if (!this._websocket) { + + function ToggleField(arg) { + this.pad[arg] = this.pad[arg] ? 0 : 1; + var main = this.svg_pad(this.this_pad_name).property('mainpainter'); + if (!main) return; + + if ((arg.indexOf('fGrid')==0) && (typeof main.DrawGrids == 'function')) + return main.DrawGrids(); + + if ((arg.indexOf('fTick')==0) && (typeof main.DrawAxes == 'function')) + return main.DrawAxes(); + } + + menu.addchk(this.pad.fGridx, 'Grid x', 'fGridx', ToggleField); + menu.addchk(this.pad.fGridy, 'Grid y', 'fGridy', ToggleField); + menu.addchk(this.pad.fTickx, 'Tick x', 'fTickx', ToggleField); + menu.addchk(this.pad.fTicky, 'Tick y', 'fTicky', ToggleField); + + this.FillAttContextMenu(menu); + } + + menu.add("separator"); + + var file_name = "canvas.png"; + if (!this.iscan) file_name = this.this_pad_name + ".png"; + + menu.add("Save as "+file_name, file_name, function(arg) { + // todo - use jqury dialog here + var top = this.svg_pad(this.this_pad_name); + if (!top.empty()) + JSROOT.AssertPrerequisites("savepng", function() { + console.log('create', arg); + top.selectAll(".btns_layer").style("display","none"); + saveSvgAsPng(top.node(), arg); + top.selectAll(".btns_layer").style("display",""); + }); + }); + + return true; + } + + JSROOT.TPadPainter.prototype.ShowContextMenu = function(evnt) { + if (!evnt) { + + // for debug purposes keep original context menu for small region in top-left corner + var pos = d3.mouse(this.svg_pad(this.this_pad_name).node()); + if (pos && (pos.length==2) && (pos[0]>0) && (pos[0]<10) && (pos[1]>0) && pos[1]<10) return; + + d3.event.stopPropagation(); // disable main context menu + d3.event.preventDefault(); // disable browser context menu + + // one need to copy event, while after call back event may be changed + evnt = d3.event; + } + + var pthis = this; + + JSROOT.Painter.createMenu(function(menu) { + menu.painter = pthis; // set as this in callbacks + + pthis.FillContextMenu(menu); + + pthis.FillObjectExecMenu(menu, function() { menu.show(evnt); }); + + }); // end menu creation + } + + JSROOT.TPadPainter.prototype.Redraw = function(resize) { + if (this.iscan) + this.CreateCanvasSvg(2); + else + this.CreatePadSvg(true); + + // at the moment canvas painter donot redraw its subitems + for (var i = 0; i < this.painters.length; ++i) + this.painters[i].Redraw(resize); + } + + JSROOT.TPadPainter.prototype.NumDrawnSubpads = function() { + if (this.painters === undefined) return 0; + + var num = 0; + + for (var i = 0; i < this.painters.length; ++i) { + var obj = this.painters[i].GetObject(); + if ((obj!==null) && (obj._typename === "TPad")) num++; + } + + return num; + } + + JSROOT.TPadPainter.prototype.RedrawByResize = function() { + if (this.access_3d_kind() === 1) return true; + + for (var i = 0; i < this.painters.length; ++i) + if (typeof this.painters[i].RedrawByResize === 'function') + if (this.painters[i].RedrawByResize()) return true; + + return false; + } + + JSROOT.TPadPainter.prototype.CheckCanvasResize = function(size, force) { + if (!this.iscan && this.has_canvas) return false; + + if (size && (typeof size === 'object') && size.force) force = true; + + if (!force) force = this.RedrawByResize(); + + var changed = this.CreateCanvasSvg(force ? 2 : 1, size); + + // if canvas changed, redraw all its subitems + if (changed) + for (var i = 0; i < this.painters.length; ++i) + this.painters[i].Redraw(true); + + return changed; + } + + JSROOT.TPadPainter.prototype.UpdateObject = function(obj) { + if (!obj || !('fPrimitives' in obj)) return false; + + this.pad.fGridx = obj.fGridx; + this.pad.fGridy = obj.fGridy; + this.pad.fTickx = obj.fTickx; + this.pad.fTicky = obj.fTicky; + this.pad.fLogx = obj.fLogx; + this.pad.fLogy = obj.fLogy; + this.pad.fLogz = obj.fLogz; + + this.pad.fUxmin = obj.fUxmin; + this.pad.fUxmax = obj.fUxmax; + this.pad.fUymin = obj.fUymin; + this.pad.fUymax = obj.fUymax; + + this.pad.fLeftMargin = obj.fLeftMargin; + this.pad.fRightMargin = obj.fRightMargin; + this.pad.fBottomMargin = obj.fBottomMargin + this.pad.fTopMargin = obj.fTopMargin; + + this.pad.fFillColor = obj.fFillColor; + this.pad.fFillStyle = obj.fFillStyle; + this.pad.fLineColor = obj.fLineColor; + this.pad.fLineStyle = obj.fLineStyle; + this.pad.fLineWidth = obj.fLineWidth; + + if (this.iscan) this.CheckColors(obj); + + var fp = this.frame_painter(); + if (fp) fp.UpdateAttributes(!fp.modified_NDC); + + var isany = false, p = 0; + for (var n = 0; n < obj.fPrimitives.arr.length; ++n) { + while (p < this.painters.length) { + var pp = this.painters[p++]; + if (!pp._primitive) continue; + if (pp.UpdateObject(obj.fPrimitives.arr[n])) isany = true; + break; + } + } + + return isany; + } + + JSROOT.TPadPainter.prototype.ItemContextMenu = function(name) { + var rrr = this.svg_pad(this.this_pad_name).node().getBoundingClientRect(); + var evnt = { clientX: rrr.left+10, clientY: rrr.top + 10 }; + + // use timeout to avoid conflict with mouse click and automatic menu close + if (name=="pad") + return setTimeout(this.ShowContextMenu.bind(this, evnt), 50); + + var selp = null, selkind; + + switch(name) { + case "xaxis": selp = this.main_painter(); selkind = "x"; break; + case "yaxis": selp = this.main_painter(); selkind = "y"; break; + case "frame": selp = this.frame_painter(); break; + default: { + var indx = parseInt(name); + if (!isNaN(indx)) selp = this.painters[indx]; + } + } + + if (!selp || (typeof selp.FillContextMenu !== 'function')) return; + + JSROOT.Painter.createMenu(function(menu) { + menu.painter = selp; + if (selp.FillContextMenu(menu,selkind)) + setTimeout(menu.show.bind(menu, evnt), 50); + }); + + } + + JSROOT.TPadPainter.prototype.PadButtonClick = function(funcname) { + + var elem = null, filename = ""; + + if (funcname == "CanvasSnapShot") { + elem = this.svg_canvas(); + filename = (this.pad ? this.pad.fName : "jsroot_canvas") + ".png"; + } else + if (funcname == "PadSnapShot") { + elem = this.svg_pad(this.this_pad_name); + filename = this.this_pad_name + ".png"; + } + if ((elem!==null) && !elem.empty()) { + var main = elem.property('mainpainter'); + + if ((elem.property('can3d') === 1) && (main!==undefined) && (main.renderer!==undefined)) { + var dataUrl = main.renderer.domElement.toDataURL("image/png"); + dataUrl.replace("image/png", "image/octet-stream"); + var link = document.createElement('a'); + if (typeof link.download === 'string') { + document.body.appendChild(link); //Firefox requires the link to be in the body + link.download = filename; + link.href = dataUrl; + link.click(); + document.body.removeChild(link); //remove the link when done + } + } else { + JSROOT.AssertPrerequisites("savepng", function() { + elem.selectAll(".btns_layer").style("display","none"); + saveSvgAsPng(elem.node(), filename); + elem.selectAll(".btns_layer").style("display",""); + }); + } + return; + } + + if (funcname == "PadContextMenus") { + + var pthis = this, evnt = d3.event; + + d3.event.preventDefault(); + d3.event.stopPropagation(); + + JSROOT.Painter.createMenu(function(menu) { + menu.painter = pthis; // set as this in callbacks + menu.add("header:Menus"); + + if (pthis.iscan) + menu.add("Canvas", "pad", pthis.ItemContextMenu); + else + menu.add("Pad", "pad", pthis.ItemContextMenu); + + if (pthis.frame_painter()) + menu.add("Frame", "frame", pthis.ItemContextMenu); + + if (pthis.main_painter()) { + menu.add("X axis", "xaxis", pthis.ItemContextMenu); + menu.add("Y axis", "yaxis", pthis.ItemContextMenu); + } + + if (pthis.painters && (pthis.painters.length>0)) { + menu.add("separator"); + var shown = []; + for (var n=0;n=0)) continue; + + var name = ('_typename' in obj) ? (obj._typename + "::") : ""; + if ('fName' in obj) name += obj.fName; + if (name.length==0) name = "item" + n; + menu.add(name, n, pthis.ItemContextMenu); + } + } + + menu.show(evnt); + }); + + return; + } + + // click automatically goes to all sub-pads + // if any painter indicates that processing completed, it returns true + var done = false; + + for (var i = 0; i < this.painters.length; ++i) { + var pp = this.painters[i]; + + if (typeof pp.PadButtonClick == 'function') + pp.PadButtonClick(funcname); + + if (!done && (typeof pp.ButtonClick == 'function')) + done = pp.ButtonClick(funcname); + } + } + + JSROOT.TPadPainter.prototype.AddButton = function(btn, tooltip, funcname) { + + // do not add buttons when not allowed + if (!JSROOT.gStyle.ToolBar) return; + + var group = this.svg_layer("btns_layer", this.this_pad_name); + if (group.empty()) return; + + // avoid buttons with duplicate names + if (!group.select("[name=" + funcname + ']').empty()) return; + + var x = group.property("nextx"); + if (x===undefined) x = 0; + + var iscan = this.iscan || !this.has_canvas; + + var svg = group.append("svg:svg") + .attr("class", "svg_toolbar_btn") + .attr("name", funcname) + .attr("x", x) + .attr("y", 0) + .attr("width",this.ButtonSize()+"px") + .attr("height",this.ButtonSize()+"px") + .attr("viewBox", "0 0 512 512") + .style("overflow","hidden"); + + svg.append("svg:title").text(tooltip + (iscan ? "" : (" on pad " + this.this_pad_name))); + + if ('recs' in btn) { + var rec = {}; + for (var n=0;n=0)) can.fFillColor = 0; + + painter.SetDivId(divid, -1); // just assign id + painter.CheckColors(can); + painter.CreateCanvasSvg(0); + painter.SetDivId(divid); // now add to painters list + + painter.AddButton(JSROOT.ToolbarIcons.camera, "Create PNG", "CanvasSnapShot"); + if (JSROOT.gStyle.ContextMenu) + painter.AddButton(JSROOT.ToolbarIcons.question, "Access context menus", "PadContextMenus"); + + if (nocanvas && opt.indexOf("noframe") < 0) + JSROOT.Painter.drawFrame(divid, null); + + painter.DrawPrimitive(0, function() { painter.DrawingReady(); }); + return painter; + } + + JSROOT.Painter.drawPad = function(divid, pad, opt) { + var painter = new JSROOT.TPadPainter(pad, false); + + if (pad && opt && (opt.indexOf("white")>=0)) pad.fFillColor = 0; + + painter.SetDivId(divid); // pad painter will be registered in the canvas painters list + + if (painter.svg_canvas().empty()) { + painter.has_canvas = false; + painter.this_pad_name = ""; + } + + painter.CreatePadSvg(); + + if (painter.MatchObjectType("TPad") && (!painter.has_canvas || painter.HasObjectsToDraw())) { + painter.AddButton(JSROOT.ToolbarIcons.camera, "Create PNG", "PadSnapShot"); + if (JSROOT.gStyle.ContextMenu) + painter.AddButton(JSROOT.ToolbarIcons.question, "Access context menus", "PadContextMenus"); + } + + var prev_name; + + if (painter.has_canvas) + // we select current pad, where all drawing is performed + prev_name = painter.CurrentPadName(painter.this_pad_name); + + painter.DrawPrimitive(0, function() { + // we restore previous pad name + painter.CurrentPadName(prev_name); + painter.DrawingReady(); + }); + + return painter; + } + + // ======================================================================= + + JSROOT.TAxisPainter = function(axis, embedded) { + JSROOT.TObjectPainter.call(this, axis); + + this.embedded = embedded; // indicate that painter embedded into the histo painter + + this.name = "yaxis"; + this.kind = "normal"; + this.func = null; + this.order = 0; // scaling order for axis labels + + this.full_min = 0; + this.full_max = 1; + this.scale_min = 0; + this.scale_max = 1; + this.ticks = []; // list of major ticks + } + + JSROOT.TAxisPainter.prototype = Object.create(JSROOT.TObjectPainter.prototype); + + JSROOT.TAxisPainter.prototype.SetAxisConfig = function(name, kind, func, min, max, smin, smax) { + this.name = name; + this.kind = kind; + this.func = func; + + this.full_min = min; + this.full_max = max; + this.scale_min = smin; + this.scale_max = smax; + } + + JSROOT.TAxisPainter.prototype.CreateFormatFuncs = function() { + + var axis = this.GetObject(), + is_gaxis = (axis && axis._typename === 'TGaxis'); + + delete this.format;// remove formatting func + + var ndiv = 508; + if (axis !== null) + ndiv = Math.max(is_gaxis ? axis.fNdiv : axis.fNdivisions, 4) ; + + this.nticks = ndiv % 100; + this.nticks2 = (ndiv % 10000 - this.nticks) / 100; + this.nticks3 = Math.floor(ndiv/10000); + + if (axis && !is_gaxis && (this.nticks > 7)) this.nticks = 7; + + var gr_range = Math.abs(this.func.range()[1] - this.func.range()[0]); + if (gr_range<=0) gr_range = 100; + + if (this.kind == 'time') { + if (this.nticks > 8) this.nticks = 8; + + var scale_range = this.scale_max - this.scale_min; + + var tf1 = JSROOT.Painter.getTimeFormat(axis); + if ((tf1.length == 0) || (scale_range < 0.1 * (this.full_max - this.full_min))) + tf1 = JSROOT.Painter.chooseTimeFormat(scale_range / this.nticks, true); + var tf2 = JSROOT.Painter.chooseTimeFormat(scale_range / gr_range, false); + + this.tfunc1 = this.tfunc2 = d3.time.format(tf1); + if (tf2!==tf1) + this.tfunc2 = d3.time.format(tf2); + + this.format = function(d, asticks) { + return asticks ? this.tfunc1(d) : this.tfunc2(d); + } + + } else + if (this.kind == 'log') { + this.nticks2 = 1; + this.noexp = axis ? axis.TestBit(JSROOT.EAxisBits.kNoExponent) : false; + if ((this.scale_max < 300) && (this.scale_min > 0.3)) this.noexp = true; + this.moreloglabels = axis ? axis.TestBit(JSROOT.EAxisBits.kMoreLogLabels) : false; + + this.format = function(d, asticks, notickexp) { + + var val = parseFloat(d); + + if (!asticks) { + var rnd = Math.round(val); + return ((rnd === val) && (Math.abs(rnd)<1e9)) ? rnd.toString() : val.toExponential(4); + } + + if (val <= 0) return null; + var vlog = JSROOT.log10(val); + if (this.moreloglabels || (Math.abs(vlog - Math.round(vlog))<0.001)) { + if (!this.noexp && !notickexp) + return JSROOT.Painter.formatExp(val.toExponential(0)); + else + if (vlog<0) + return val.toFixed(Math.round(-vlog+0.5)); + else + return val.toFixed(0); + } + return null; + } + } else + if (this.kind == 'labels') { + this.nticks = 50; // for text output allow max 50 names + var scale_range = this.scale_max - this.scale_min; + if (this.nticks > scale_range) + this.nticks = Math.round(scale_range); + this.nticks2 = 1; + + this.axis = axis; + + this.format = function(d) { + var indx = Math.round(parseInt(d)) + 1; + if ((indx<1) || (indx>this.axis.fNbins)) return null; + for (var i = 0; i < this.axis.fLabels.arr.length; ++i) { + var tstr = this.axis.fLabels.arr[i]; + if (tstr.fUniqueID == indx) return tstr.fString; + } + return null; + } + } else { + + this.range = Math.abs(this.scale_max - this.scale_min); + if (this.range <= 0) + this.ndig = -3; + else + this.ndig = Math.round(JSROOT.log10(this.nticks / this.range) + 0.7); + + this.format = function(d, asticks) { + var val = parseFloat(d), rnd = Math.round(val); + if (asticks) { + if (this.order===0) { + if (val === rnd) return rnd.toString(); + if (Math.abs(val) < 1e-10 * this.range) return 0; + val = val.toFixed(this.ndig > 0 ? this.ndig : 0); + if ((typeof d == 'string') && (d.length <= val.length+1)) return d; + return val; + } + val = val / Math.pow(10, this.order); + rnd = Math.round(val); + if (val === rnd) return rnd.toString(); + return val.toFixed(this.ndig + this.order > 0 ? this.ndig + this.order : 0 ); + } + + if (val === rnd) + return (Math.abs(rnd)<1e9) ? rnd.toString() : val.toExponential(4); + return val.toFixed(this.ndig+2 > 0 ? this.ndig+2 : 0); + } + } + } + + JSROOT.TAxisPainter.prototype.CreateTicks = function() { + // function used to create array with minor/middle/major ticks + + var handle = { nminor: 0, nmiddle: 0, nmajor: 0, func: this.func }; + + handle.minor = handle.middle = handle.major = this.func.ticks(this.nticks); + + if (this.nticks2 > 1) { + handle.minor = handle.middle = this.func.ticks(handle.major.length * this.nticks2); + + var gr_range = Math.abs(this.func.range()[1] - this.func.range()[0]); + + // avoid black filling by middle-size + if ((handle.middle.length <= handle.major.length) || (handle.middle.length > gr_range/3.5)) { + handle.minor = handle.middle = handle.major; + } else + if ((this.nticks3 > 1) && (this.kind !== 'log')) { + handle.minor = this.func.ticks(handle.middle.length * this.nticks3); + if ((handle.minor.length <= handle.middle.length) || (handle.minor.length > gr_range/1.7)) handle.minor = handle.middle; + } + } + + handle.reset = function() { + this.nminor = this.nmiddle = this.nmajor = 0; + } + + handle.next = function(doround) { + if (this.nminor >= this.minor.length) return false; + + this.tick = this.minor[this.nminor++]; + this.grpos = this.func(this.tick); + if (doround) this.grpos = Math.round(this.grpos); + this.kind = 3; + + if ((this.nmiddle < this.middle.length) && (Math.abs(this.grpos - this.func(this.middle[this.nmiddle])) < 1)) { + this.nmiddle++; + this.kind = 2; + } + + if ((this.nmajor < this.major.length) && (Math.abs(this.grpos - this.func(this.major[this.nmajor])) < 1) ) { + this.nmajor++; + this.kind = 1; + } + return true; + } + + handle.last_major = function() { + return (this.kind !== 1) ? false : this.nmajor == this.major.length; + } + + handle.next_major_grpos = function() { + if (this.nmajor >= this.major.length) return null; + return this.func(this.major[this.nmajor]); + } + + return handle; + } + + JSROOT.TAxisPainter.prototype.IsCenterLabels = function() { + if (this.kind === 'labels') return true; + if (this.kind === 'log') return false; + var axis = this.GetObject(); + return axis && axis.TestBit(JSROOT.EAxisBits.kCenterLabels); + } + + JSROOT.TAxisPainter.prototype.DrawAxis = function(vertical, layer, w, h, transform, reverse, second_shift) { + // function draw complete TAxis + // later will be used to draw TGaxis + + var axis = this.GetObject(), + is_gaxis = (axis && axis._typename === 'TGaxis'), + side = (this.name === "zaxis") ? -1 : 1, both_sides = 0, + axis_g = layer, tickSize = 10, scaling_size = 100, text_scaling_size = 100; + + this.vertical = vertical; + + // shift for second ticks set (if any) + if (!second_shift) second_shift = 0; + + if (is_gaxis) { + if (!this.lineatt) this.lineatt = JSROOT.Painter.createAttLine(axis); + scaling_size = (vertical ? this.pad_width() : this.pad_height()); + text_scaling_size = Math.min(this.pad_width(), this.pad_height()); + tickSize = Math.round(axis.fTickSize * scaling_size); + } else { + if (!this.lineatt) this.lineatt = JSROOT.Painter.createAttLine(axis.fAxisColor, 1); + scaling_size = (vertical ? w : h); + tickSize = Math.round(axis.fTickLength * scaling_size); + text_scaling_size = Math.min(w,h); + } + + if (!is_gaxis || (this.name === "zaxis")) { + axis_g = layer.select("." + this.name + "_container"); + if (axis_g.empty()) + axis_g = layer.append("svg:g").attr("class",this.name+"_container"); + else + axis_g.selectAll("*").remove(); + } else { + + if ((axis.fChopt.indexOf("-")>=0) && (axis.fChopt.indexOf("+")<0)) side = -1; else + if (vertical && axis.fChopt=="+L") side = -1; else + if ((axis.fChopt.indexOf("-")>=0) && (axis.fChopt.indexOf("+")>=0)) { side = 1; both_sides = 1; } + + axis_g.append("svg:line") + .attr("x1",0).attr("y1",0) + .attr("x1",vertical ? 0 : w) + .attr("y1", vertical ? h : 0) + .call(this.lineatt.func); + } + + if (transform !== undefined) + axis_g.attr("transform", transform); + + this.CreateFormatFuncs(); + + var center_lbls = this.IsCenterLabels(), + res = "", res2 = "", lastpos = 0, lasth = 0, textscale = 1; + + // first draw ticks + + this.ticks = []; + + var handle = this.CreateTicks(); + + while (handle.next(true)) { + var h1 = Math.round(tickSize/4), h2 = 0; + + if (handle.kind < 3) + h1 = Math.round(tickSize/2); + + if (handle.kind == 1) { + // if not showing lables, not show large tick + if (!('format' in this) || (this.format(handle.tick,true)!==null)) h1 = tickSize; + this.ticks.push(handle.grpos); // keep graphical positions of major ticks + } + + if (both_sides > 0) h2 = -h1; else + if (side < 0) { h2 = -h1; h1 = 0; } else { h2 = 0; } + + if (res.length == 0) { + res = vertical ? ("M"+h1+","+handle.grpos) : ("M"+handle.grpos+","+(-h1)); + res2 = vertical ? ("M"+(second_shift-h1)+","+handle.grpos) : ("M"+handle.grpos+","+(second_shift+h1)); + } else { + res += vertical ? ("m"+(h1-lasth)+","+(handle.grpos-lastpos)) : ("m"+(handle.grpos-lastpos)+","+(lasth-h1)); + res2 += vertical ? ("m"+(lasth-h1)+","+(handle.grpos-lastpos)) : ("m"+(handle.grpos-lastpos)+","+(h1-lasth)); + } + + res += vertical ? ("h"+ (h2-h1)) : ("v"+ (h1-h2)); + res2 += vertical ? ("h"+ (h1-h2)) : ("v"+ (h2-h1)); + + lastpos = handle.grpos; + lasth = h2; + } + + if (res.length > 0) + axis_g.append("svg:path").attr("d", res).call(this.lineatt.func); + + if ((second_shift!==0) && (res2.length>0)) + axis_g.append("svg:path").attr("d", res2).call(this.lineatt.func); + + var last = vertical ? h : 0, + labelsize = (axis.fLabelSize >= 1) ? axis.fLabelSize : Math.round(axis.fLabelSize * (is_gaxis ? this.pad_height() : h)), + labelfont = JSROOT.Painter.getFontDetails(axis.fLabelFont, labelsize), + label_color = JSROOT.Painter.root_colors[axis.fLabelColor], + labeloffset = 3 + Math.round(axis.fLabelOffset * scaling_size), + label_g = axis_g.append("svg:g") + .attr("class","axis_labels") + .call(labelfont.func); + + this.order = 0; + if ((this.kind=="normal") && vertical && !axis.TestBit(JSROOT.EAxisBits.kNoExponent)) { + var maxtick = Math.max(Math.abs(handle.major[0]),Math.abs(handle.major[handle.major.length-1])); + for(var order=18;order>-18;order-=3) { + if (order===0) continue; + if ((order<0) && ((this.range>=0.1) || (maxtick>=1.))) break; + var mult = Math.pow(10, order); + if ((this.range > mult * 9.99999) || ((maxtick > mult*50) && (this.range > mult * 0.05))) { + this.order = order; + break; + } + } + } + + for (var nmajor=0;nmajor 0) ? "end" : "start") + .style("dominant-baseline", "middle"); + else + t.attr("x", pos) + .attr("y", 2+labeloffset*side + both_sides*tickSize) + .attr("dy", (side > 0) ? ".7em" : "-.3em") + .style("text-anchor", "middle"); + + var tsize = this.GetBoundarySizes(t.node()); + var space_before = (nmajor > 0) ? (pos - last) : (vertical ? h/2 : w/2); + var space_after = (nmajor < handle.major.length-1) ? (Math.round(this.func(handle.major[nmajor+1])) - pos) : space_before; + var space = Math.min(Math.abs(space_before), Math.abs(space_after)); + + if (vertical) { + + if ((space > 0) && (tsize.height > 5) && (this.kind !== 'log')) + textscale = Math.min(textscale, space / tsize.height); + + if (center_lbls) { + // if position too far top, remove label + if (pos + space_after/2 - textscale*tsize.height/2 < -10) + t.remove(); + else + t.attr("y", Math.round(pos + space_after/2)); + } + + } else { + + // test if label consume too much space + if ((space > 0) && (tsize.width > 10) && (this.kind !== 'log')) + textscale = Math.min(textscale, space / tsize.width); + + if (center_lbls) { + // if position too far right, remove label + if (pos + space_after/2 - textscale*tsize.width/2 > w - 10) + t.remove(); + else + t.attr("x", Math.round(pos + space_after/2)); + } + } + + last = pos; + } + + if (this.order!==0) { + var val = Math.pow(10,this.order).toExponential(0); + + var t = label_g.append("svg:text").attr("fill", label_color).text('\xD7' + JSROOT.Painter.formatExp(val)); + + if (vertical) + t.attr("x", labeloffset) + .attr("y", 0) + .style("text-anchor", "start") + .style("dominant-baseline", "middle") + .attr("dy", "-.5em"); + } + + + if ((textscale>0) && (textscale<1.)) { + // rotate X lables if they are too big + if ((textscale < 0.7) && !vertical && (side>0)) { + label_g.selectAll("text").each(function() { + var txt = d3.select(this), x = txt.attr("x"), y = txt.attr("y") - 5; + + txt.attr("transform", "translate(" + x + "," + y + ") rotate(25)") + .style("text-anchor", "start") + .attr("x",null).attr("y",null); + }); + textscale *= 3.5; + } + // round to upper boundary for calculated value like 4.4 + labelfont.size = Math.floor(labelfont.size * textscale + 0.7); + label_g.call(labelfont.func); + } + + if (axis.fTitle.length > 0) { + var title_g = axis_g.append("svg:g").attr("class", "axis_title"), + title_fontsize = (axis.fTitleSize >= 1) ? axis.fTitleSize : Math.round(axis.fTitleSize * text_scaling_size), + center = axis.TestBit(JSROOT.EAxisBits.kCenterTitle), + rotate = axis.TestBit(JSROOT.EAxisBits.kRotateTitle) ? -1 : 1, + title_color = JSROOT.Painter.root_colors[axis.fTitleColor]; + + this.StartTextDrawing(axis.fTitleFont, title_fontsize, title_g); + + var myxor = ((rotate<0) && !reverse) || ((rotate>=0) && reverse); + + if (vertical) { + var xoffset = -side*Math.round(labeloffset + (2-side/10) * axis.fTitleOffset*title_fontsize); + + if ((this.name == "zaxis") && is_gaxis && ('getBoundingClientRect' in axis_g.node())) { + // special handling for color palette labels - draw them always on right side + var rect = axis_g.node().getBoundingClientRect(); + if (xoffset < rect.width - tickSize) xoffset = Math.round(rect.width - tickSize); + } + + this.DrawText((center ? "middle" : (myxor ? "begin" : "end" ))+ ";middle", + xoffset, + Math.round(center ? h/2 : (reverse ? h : 0)), + 0, (rotate<0 ? -90 : -270), + axis.fTitle, title_color, 1, title_g); + } else { + this.DrawText((center ? 'middle' : (myxor ? 'begin' : 'end')) + ";middle", + Math.round(center ? w/2 : (reverse ? 0 : w)), + Math.round(side*(labeloffset + 1.9*title_fontsize*axis.fTitleOffset)), + 0, (rotate<0 ? -180 : 0), + axis.fTitle, title_color, 1, title_g); + } + + this.FinishTextDrawing(title_g); + } + + + if (JSROOT.gStyle.Zooming) { + var r = axis_g.append("svg:rect") + .attr("class", "axis_zoom") + .style("opacity", "0") + .style("cursor", "crosshair"); + + if (vertical) + r.attr("x", (side >0) ? (-2*labelfont.size - 3) : 3) + .attr("y", 0) + .attr("width", 2*labelfont.size + 3) + .attr("height", h) + else + r.attr("x", 0).attr("y", 0) + .attr("width", w).attr("height", labelfont.size + 3); + } + + this.position = 0; + + if ('getBoundingClientRect' in axis_g.node()) { + var rect1 = axis_g.node().getBoundingClientRect(), + rect2 = this.svg_pad().node().getBoundingClientRect(); + + this.position = rect1.left - rect2.left; // use to control left position of Y scale + } + } + + JSROOT.TAxisPainter.prototype.Redraw = function() { + + var gaxis = this.GetObject(), + x1 = Math.round(this.AxisToSvg("x", gaxis.fX1)), + y1 = Math.round(this.AxisToSvg("y", gaxis.fY1)), + x2 = Math.round(this.AxisToSvg("x", gaxis.fX2)), + y2 = Math.round(this.AxisToSvg("y", gaxis.fY2)), + w = x2 - x1, h = y1 - y2; + + var vertical = w<5, + kind = "normal", + func = null, + min = gaxis.fWmin, + max = gaxis.fWmax, + reverse = false; + + if (gaxis.fChopt.indexOf("G")>=0) { + func = d3.scale.log(); + kind = "log"; + } else { + func = d3.scale.linear(); + } + + func.domain([min, max]); + + if (vertical) { + if (h > 0) { + func.range([h,0]); + } else { + var d = y1; y1 = y2; y2 = d; + h = -h; reverse = true; + func.range([0,h]); + } + } else { + if (w > 0) { + func.range([0,w]); + } else { + var d = x1; x1 = x2; x2 = d; + w = -w; reverse = true; + func.range([w,0]); + } + } + + this.SetAxisConfig(vertical ? "yaxis" : "xaxis", kind, func, min, max, min, max); + + this.RecreateDrawG(true, "text_layer"); + + this.DrawAxis(vertical, this.draw_g, w, h, "translate(" + x1 + "," + y2 +")", reverse); + } + + + JSROOT.drawGaxis = function(divid, obj, opt) { + var painter = new JSROOT.TAxisPainter(obj, false); + + painter.SetDivId(divid); + + painter.Redraw(); + + return painter.DrawingReady(); + } + + + // ============================================================= + + JSROOT.THistPainter = function(histo) { + JSROOT.TObjectPainter.call(this, histo); + this.histo = histo; + this.shrink_frame_left = 0.; + this.draw_content = true; + this.nbinsx = 0; + this.nbinsy = 0; + this.x_kind = 'normal'; // 'normal', 'time', 'labels' + this.y_kind = 'normal'; // 'normal', 'time', 'labels' + } + + JSROOT.THistPainter.prototype = Object.create(JSROOT.TObjectPainter.prototype); + + JSROOT.THistPainter.prototype.IsDummyHisto = function() { + return (this.histo==null) || !this.draw_content || (this.options.Axis>0); + } + + JSROOT.THistPainter.prototype.IsTProfile = function() { + return this.MatchObjectType('TProfile'); + } + + JSROOT.THistPainter.prototype.IsTH2Poly = function() { + return this.histo && this.histo._typename.match(/^TH2Poly/); + } + + JSROOT.THistPainter.prototype.Dimension = function() { + if (!this.histo) return 0; + if (this.histo._typename.indexOf("TH2")==0) return 2; + if (this.histo._typename.indexOf("TH3")==0) return 3; + return 1; + } + + JSROOT.THistPainter.prototype.DecodeOptions = function(opt) { + + if ((opt == null) || (opt == "")) opt = this.histo.fOption; + + /* decode string 'opt' and fill the option structure */ + var hdim = this.Dimension(); + var option = { + Axis: 0, Bar: 0, Curve: 0, Error: 0, Hist: 0, Line: 0, + Mark: 0, Fill: 0, Same: 0, Scat: 0, Func: 0, Star: 0, + Arrow: 0, Box: 0, Text: 0, Char: 0, Color: 0, Contour: 0, + Lego: 0, Surf: 0, Off: 0, Tri: 0, Proj: 0, AxisPos: 0, + Spec: 0, Pie: 0, List: 0, Zscale: 0, FrontBox: 1, BackBox: 1, Candle: "", + System: JSROOT.Painter.Coord.kCARTESIAN, + AutoColor : 0, NoStat : 0, AutoZoom : false, + HighRes: 0, Zero: 0, Palette: 0, Optimize: JSROOT.gStyle.OptimizeDraw + }; + // check for graphical cuts + var chopt = JSROOT.Painter.clearCuts(opt.toUpperCase()); + + var pad = this.root_pad(); + + // if (hdim > 1) option.Scat = 1; // default was scatter plot + + // use error plot only when any sumw2 bigger than 0 + if ((hdim===1) && (this.histo.fSumw2.length > 0)) + for (var n=0;n 0) { option.Error = 2; break; } + + if (this.histo.fFunctions !== null) option.Func = 1; + + var i = chopt.indexOf('PAL'); + if (i>=0) { + var i2 = i+3; + while ((i2=48) && (chopt.charCodeAt(i2)<58)) ++i2; + if (i2>i+3) { + option.Palette = parseInt(chopt.substring(i+3,i2)); + chopt = chopt.replace(chopt.substring(i,i2),""); + } + } + + + var part = ""; // used to return part of string + + function check(name,postpart) { + var pos = chopt.indexOf(name); + if (pos < 0) return false; + chopt = chopt.substr(0, pos) + chopt.substr(pos + name.length); + if (postpart) { + part = ""; + var pos2 = pos; + while ((pos2 pos) { + part = chopt.substr(pos, pos2-pos); + chopt = chopt.substr(0, pos) + chopt.substr(pos2); + } + } + return true; + } + + + if (check('NOOPTIMIZE')) option.Optimize = 0; + if (check('OPTIMIZE')) option.Optimize = 2; + + if (check('AUTOCOL')) { option.AutoColor = 1; option.Hist = 1; } + if (check('AUTOZOOM')) { option.AutoZoom = 1; option.Hist = 1; } + + if (check('NOSTAT')) option.NoStat = 1; + + if (check('LOGX')) pad.fLogx = 1; + if (check('LOGY')) pad.fLogy = 1; + if (check('LOGZ')) pad.fLogz = 1; + if (check('GRIDX')) pad.fGridx = 1; + if (check('GRIDY')) pad.fGridy = 1; + if (check('TICKX')) pad.fTickx = 1; + if (check('TICKY')) pad.fTicky = 1; + + var nch = chopt.length; + if (!nch) option.Hist = 1; + + if (check('SPEC')) { + option.Scat = 0; + option.Spec = Math.max(1600, check('BF(') ? parseInt(chopt) : 0); + } + + check('GL'); + + if (check('X+')) option.AxisPos = 10; + if (check('Y+')) option.AxisPos += 1; + + if ((option.AxisPos == 10 || option.AxisPos == 1) && (nch == 2)) + option.Hist = 1; + + if (option.AxisPos == 11 && (nch == 4)) + option.Hist = 1; + + if (check('SAMES')) { + if (nch == 5) option.Hist = 1; + option.Same = 2; + } + + if (check('SAME')) { + if (nch == 4) option.Hist = 1; + option.Same = 1; + } + + if (check('PIE')) option.Pie = 1; + + if (check('CANDLE', true)) option.Candle = part; + + if (check('LEGO', true)) { + option.Scat = 0; + option.Lego = 1; + if (part.indexOf('0') >= 0) option.Zero = 1; + if (part.indexOf('1') >= 0) option.Lego = 11; + if (part.indexOf('2') >= 0) option.Lego = 12; + if (part.indexOf('3') >= 0) option.Lego = 13; + if (part.indexOf('4') >= 0) option.Lego = 14; + if (part.indexOf('FB') >= 0) option.FrontBox = 0; + if (part.indexOf('BB') >= 0) option.BackBox = 0; + if (part.indexOf('Z')>=0) option.Zscale = 1; + } + + if (check('SURF', true)) { + option.Scat = 0; + option.Surf = 1; + if (part.indexOf('FB') >= 0) { option.FrontBox = 0; part = part.replace('FB',''); } + if (part.indexOf('BB') >= 0) { option.BackBox = 0; part = part.replace('BB',''); } + if ((part.length>0) && !isNaN(parseInt(part))) option.Surf = 10 + parseInt(part); + } + + if (check('TF3', true)) { + if (part.indexOf('FB') >= 0) option.FrontBox = 0; + if (part.indexOf('BB') >= 0) option.BackBox = 0; + } + + if (check('ISO', true)) { + if (part.indexOf('FB') >= 0) option.FrontBox = 0; + if (part.indexOf('BB') >= 0) option.BackBox = 0; + } + + if (check('LIST')) option.List = 1; + + if (check('CONT', true)) { + if (hdim > 1) { + option.Scat = 0; + option.Contour = 1; + if (!isNaN(parseInt(part))) option.Contour = 10 + parseInt(part); + } else { + option.Hist = 1; + } + } + + // decode bar/hbar option + if (check('HBAR', true)) option.Bar = 20; else + if (check('BAR', true)) option.Bar = 10; + if (option.Bar > 0) { + option.Hist = 0; + if (!isNaN(parseInt(part))) option.Bar += parseInt(part); + } + + if (check('ARR')) { + if (hdim > 1) { + option.Arrow = 1; + option.Scat = 0; + } else { + option.Hist = 1; + } + } + + if (check('BOX1')) option.Box = 11; else + if (check('BOX')) option.Box = 1; + + if (option.Box) + if (hdim > 1) option.Scat = 0; + else option.Hist = 1; + + if (check('COL', true)) { + option.Color = 1; + + if (part[0]=='0') option.Color = 111; + if (part[0]=='1') option.Color = 1; + if (part[0]=='2') option.Color = 2; + if (part[0]=='3') option.Color = 3; + + if (part.indexOf('Z')>=0) option.Zscale = 1; + if (hdim == 1) option.Hist = 1; + else option.Scat = 0; + } + + if (check('CHAR')) { option.Char = 1; option.Scat = 0; } + if (check('FUNC')) { option.Func = 2; option.Hist = 0; } + if (check('HIST')) { option.Hist = 2; option.Func = 0; option.Error = 0; } + if (check('AXIS')) option.Axis = 1; + if (check('AXIG')) option.Axis = 2; + + if (check('TEXT', true)) { + option.Text = 1; + option.Scat = 0; + + var angle = parseInt(part); + if (!isNaN(angle)) { + if (angle < 0) angle = 0; + if (angle > 90) angle = 90; + option.Text = 1000 + angle; + } + if (part.indexOf('N')>=0 && this.IsTH2Poly()) + option.Text += 3000; + } + + if (check('SCAT')) option.Scat = 1; + if (check('POL')) option.System = JSROOT.Painter.Coord.kPOLAR; + if (check('CYL')) option.System = JSROOT.Painter.Coord.kCYLINDRICAL; + if (check('SPH')) option.System = JSROOT.Painter.Coord.kSPHERICAL; + if (check('PSR')) option.System = JSROOT.Painter.Coord.kRAPIDITY; + + if (check('TRI', true)) { + option.Scat = 0; + option.Color = 0; + option.Tri = 1; + if (part.indexOf('FB') >= 0) option.FrontBox = 0; + if (part.indexOf('BB') >= 0) option.BackBox = 0; + if (part.indexOf('ERR') >= 0) option.Error = 1; + } + if (check('AITOFF')) option.Proj = 1; + if (check('MERCATOR')) option.Proj = 2; + if (check('SINUSOIDAL')) option.Proj = 3; + if (check('PARABOLIC')) option.Proj = 4; + + if (option.Proj > 0) { option.Scat = 0; option.Contour = 14; } + + if ((hdim==3) && check('FB')) option.FrontBox = 0; + if ((hdim==3) && check('BB')) option.BackBox = 0; + + if (check('A')) option.Axis = -1; + if (check('B')) { option.Bar = 1; option.Hist = -1; } + if (check('C')) { option.Curve = 1; option.Hist = -1; } + if (check('F')) option.Fill = 1; + if (check('][')) { option.Off = 1; option.Hist = 1; } + if (check('F2')) option.Fill = 2; + if (check('L')) { option.Line = 1; option.Hist = -1; } + + if (check('P0')) { option.Mark = 10; option.Hist = -1; } + if (check('P')) { option.Mark = 1; option.Hist = -1; } + if (check('Z')) option.Zscale = 1; + if (check('*')) option.Star = 1; + if (check('H')) option.Hist = 2; + + if (this.IsTH2Poly()) { + if (option.Fill + option.Line + option.Mark != 0) option.Scat = 0; + } + + if (check('E', true)) { + if (hdim == 1) { + option.Error = 1; + if ((part.length>0) && !isNaN(parseInt(part[0]))) + option.Error = 10 + parseInt(part[0]); + if (part.indexOf('X0')>=0) { + if (option.Error == 1) option.Error += 20; + option.Error += 10; + } + if (option.Text && this.IsTProfile()) { + option.Text += 2000; + option.Error = 0; + } + } else { + if (option.Error == 0) { + option.Error = 100; + option.Scat = 0; + } + if (option.Text) { + option.Text += 2000; + option.Error = 0; + } + } + } + if (check('9')) option.HighRes = 1; + + //if (option.Surf == 15) + // if (option.System == JSROOT.Painter.Coord.kPOLAR || option.System == JSROOT.Painter.Coord.kCARTESIAN) + // option.Surf = 13; + + return option; + } + + JSROOT.THistPainter.prototype.GetAutoColor = function(col) { + if (this.options.AutoColor<=0) return col; + + var id = this.options.AutoColor; + this.options.AutoColor = id % 8 + 1; + return JSROOT.Painter.root_colors[id]; + } + + JSROOT.THistPainter.prototype.ScanContent = function() { + // function will be called once new histogram or + // new histogram content is assigned + // one should find min,max,nbins, maxcontent values + + alert("HistPainter.prototype.ScanContent not implemented"); + } + + JSROOT.THistPainter.prototype.CheckPadRange = function() { + + if (!this.is_main_painter()) return; + + this.zoom_xmin = this.zoom_xmax = 0; + this.zoom_ymin = this.zoom_ymax = 0; + this.zoom_zmin = this.zoom_zmax = 0; + + var pad = this.root_pad(); + + if (!pad || !('fUxmin' in pad) || this.create_canvas) return; + + var min = pad.fUxmin, max = pad.fUxmax, xaxis = this.histo.fXaxis; + + // first check that non-default values are there + if ((this.Dimension() < 3) && ((min !== 0) || (max !== 1))) { + if (pad.fLogx > 0) { + min = Math.exp(min * Math.log(10)); + max = Math.exp(max * Math.log(10)); + } + + if (min !== xaxis.fXmin || max !== xaxis.fXmax) + if (min >= xaxis.fXmin && max <= xaxis.fXmax) { + // set zoom values if only inside range + this.zoom_xmin = min; + this.zoom_xmax = max; + } + } + + // apply selected user range if range not selected via pad + if (xaxis.TestBit(JSROOT.EAxisBits.kAxisRange)) { + xaxis.InvertBit(JSROOT.EAxisBits.kAxisRange); // axis range is not used for main painter + if ((this.zoom_xmin === this.zoom_xmax) && (xaxis.fFirst !== xaxis.fLast) && + ((xaxis.fFirst > 1) || (xaxis.fLast < xaxis.fNbins))) { + this.zoom_xmin = xaxis.fFirst > 1 ? xaxis.GetBinLowEdge(xaxis.fFirst-1) : xaxis.fXmin; + this.zoom_xmax = xaxis.fLast < xaxis.fNbins ? xaxis.GetBinLowEdge(xaxis.fLast) : xaxis.fXmax; + } + } + + min = pad.fUymin; max = pad.fUymax; + + if ((this.Dimension() == 2) && ((min !== 0) || (max !== 1))) { + if (pad.fLogy > 0) { + min = Math.exp(min * Math.log(10)); + max = Math.exp(max * Math.log(10)); + } + + if (min !== this.histo.fYaxis.fXmin || max !== this.histo.fYaxis.fXmax) + if (min >= this.histo.fYaxis.fXmin && max <= this.histo.fYaxis.fXmax) { + // set zoom values if only inside range + this.zoom_ymin = min; + this.zoom_ymax = max; + } + } + } + + JSROOT.THistPainter.prototype.CheckHistDrawAttributes = function() { + + if (!this.fillatt || !this.fillatt.changed) + this.fillatt = this.createAttFill(this.histo, undefined, undefined, 1); + + if (!this.lineatt || !this.lineatt.changed) { + this.lineatt = JSROOT.Painter.createAttLine(this.histo); + var main = this.main_painter(); + + if (main) { + var newcol = main.GetAutoColor(this.lineatt.color); + if (newcol !== this.lineatt.color) { this.lineatt.color = newcol; this.lineatt.changed = true; } + } + } + } + + JSROOT.THistPainter.prototype.UpdateObject = function(obj) { + if (!this.MatchObjectType(obj)) { + alert("JSROOT.THistPainter.UpdateObject - wrong class " + obj._typename + " expected " + this.histo._typename); + return false; + } + + // TODO: simple replace of object does not help - one can have different + // complex relations between histo and stat box, histo and colz axis, + // one could have THStack or TMultiGraph object + // The only that could be done is update of content + + // this.histo = obj; + + var histo = this.GetObject(); + + histo.fFillColor = obj.fFillColor; + histo.fFillStyle = obj.fFillStyle; + histo.fLineColor = obj.fLineColor; + histo.fLineStyle = obj.fLineStyle; + histo.fLineWidth = obj.fLineWidth; + + histo.fEntries = obj.fEntries; + histo.fTsumw = obj.fTsumw; + histo.fTsumwx = obj.fTsumwx; + histo.fTsumwx2 = obj.fTsumwx2; + if (this.Dimension() == 2) { + histo.fTsumwy = obj.fTsumwy; + histo.fTsumwy2 = obj.fTsumwy2; + histo.fTsumwxy = obj.fTsumwxy; + } + histo.fArray = obj.fArray; + histo.fNcells = obj.fNcells; + histo.fTitle = obj.fTitle; + histo.fMinimum = obj.fMinimum; + histo.fMaximum = obj.fMaximum; + histo.fXaxis.fNbins = obj.fXaxis.fNbins; + if (!this.main_painter().zoom_changed_interactive) { + histo.fXaxis.fXmin = obj.fXaxis.fXmin; + histo.fXaxis.fXmax = obj.fXaxis.fXmax; + histo.fXaxis.fFirst = obj.fXaxis.fFirst; + histo.fXaxis.fLast = obj.fXaxis.fLast; + histo.fXaxis.fBits = obj.fXaxis.fBits; + histo.fYaxis.fXmin = obj.fYaxis.fXmin; + histo.fYaxis.fXmax = obj.fYaxis.fXmax; + histo.fYaxis.fFirst = obj.fYaxis.fFirst; + histo.fYaxis.fLast = obj.fYaxis.fLast; + histo.fYaxis.fBits = obj.fYaxis.fBits; + } + histo.fSumw2 = obj.fSumw2; + + if (this.IsTProfile()) { + histo.fBinEntries = obj.fBinEntries; + } + + if (obj.fFunctions) + for (var n=0;n this.nbinsx) this.xmax; + if (indx==bin) return this.histo.fXaxis.fXbins[indx]; + var indx2 = (bin < indx) ? indx - 1 : indx + 1; + return this.histo.fXaxis.fXbins[indx] * Math.abs(bin-indx2) + this.histo.fXaxis.fXbins[indx2] * Math.abs(bin-indx); + }; + this.GetIndexX = function(x,add) { + for (var k = 1; k < this.histo.fXaxis.fXbins.length; ++k) + if (x < this.histo.fXaxis.fXbins[k]) return Math.floor(k-1+add); + return this.nbinsx; + }; + } else { + this.regularx = true; + this.binwidthx = (this.xmax - this.xmin); + if (this.nbinsx > 0) + this.binwidthx = this.binwidthx / this.nbinsx; + + this.GetBinX = function(bin) { return this.xmin + bin*this.binwidthx; }; + this.GetIndexX = function(x,add) { return Math.floor((x - this.xmin) / this.binwidthx + add); }; + } + + this.ymin = this.histo.fYaxis.fXmin; + this.ymax = this.histo.fYaxis.fXmax; + + if (!with_y_axis || (this.nbinsy==0)) return; + + if (this.histo.fYaxis.fXbins.length == this.nbinsy+1) { + this.regulary = false; + this.GetBinY = function(bin) { + var indx = Math.round(bin); + if (indx <= 0) return this.ymin; + if (indx > this.nbinsy) this.ymax; + if (indx==bin) return this.histo.fYaxis.fXbins[indx]; + var indx2 = (bin < indx) ? indx - 1 : indx + 1; + return this.histo.fYaxis.fXbins[indx] * Math.abs(bin-indx2) + this.histo.fYaxis.fXbins[indx2] * Math.abs(bin-indx); + }; + this.GetIndexY = function(y,add) { + for (var k = 1; k < this.histo.fYaxis.fXbins.length; ++k) + if (y < this.histo.fYaxis.fXbins[k]) return Math.floor(k-1+add); + return this.nbinsy; + }; + } else { + this.regulary = true; + this.binwidthy = (this.ymax - this.ymin); + if (this.nbinsy > 0) + this.binwidthy = this.binwidthy / this.nbinsy; + + this.GetBinY = function(bin) { return this.ymin+bin*this.binwidthy; }; + this.GetIndexY = function(y,add) { return Math.floor((y - this.ymin) / this.binwidthy + add); }; + } + + if (!with_z_axis || (this.nbinsz==0)) return; + + if (this.histo.fZaxis.fXbins.length == this.nbinsz+1) { + this.regularz = false; + this.GetBinZ = function(bin) { + var indx = Math.round(bin); + if (indx <= 0) return this.zmin; + if (indx > this.nbinsz) this.zmax; + if (indx==bin) return this.histo.fZaxis.fXbins[indx]; + var indx2 = (bin < indx) ? indx - 1 : indx + 1; + return this.histo.fZaxis.fXbins[indx] * Math.abs(bin-indx2) + this.histo.fZaxis.fXbins[indx2] * Math.abs(bin-indx); + }; + this.GetIndexZ = function(z,add) { + for (var k = 1; k < this.histo.fZaxis.fXbins.length; ++k) + if (z < this.histo.fZaxis.fXbins[k]) return Math.floor(k-1+add); + return this.nbinsz; + }; + } else { + this.regularz = true; + this.binwidthz = (this.zmax - this.zmin); + if (this.nbinsz > 0) + this.binwidthz = this.binwidthz / this.nbinsz; + + this.GetBinZ = function(bin) { return this.zmin+bin*this.binwidthz; }; + this.GetIndexZ = function(z,add) { return Math.floor((z - this.zmin) / this.binwidthz + add); }; + } + } + + + JSROOT.THistPainter.prototype.CreateXY = function() { + // here we create x,y objects which maps our physical coordnates into pixels + // while only first painter really need such object, all others just reuse it + // following functions are introduced + // this.GetBin[X/Y] return bin coordinate + // this.Convert[X/Y] converts root value in JS date when date scale is used + // this.[x,y] these are d3.scale objects + // this.gr[x,y] converts root scale into graphical value + // this.Revert[X/Y] converts graphical coordinates to root scale value + + if (!this.is_main_painter()) { + this.x = this.main_painter().x; + this.y = this.main_painter().y; + return; + } + + this.swap_xy = false; + if (this.options.Bar>=20) this.swap_xy = true; + this.logx = this.logy = false; + + var w = this.frame_width(), h = this.frame_height(), pad = this.root_pad(); + + if (this.histo.fXaxis.fTimeDisplay) { + this.x_kind = 'time'; + this.timeoffsetx = JSROOT.Painter.getTimeOffset(this.histo.fXaxis); + this.ConvertX = function(x) { return new Date(this.timeoffsetx + x*1000); }; + this.RevertX = function(grx) { return (this.x.invert(grx) - this.timeoffsetx) / 1000; }; + } else { + this.x_kind = (this.histo.fXaxis.fLabels==null) ? 'normal' : 'labels'; + this.ConvertX = function(x) { return x; }; + this.RevertX = function(grx) { return this.x.invert(grx); }; + } + + this.scale_xmin = this.xmin; + this.scale_xmax = this.xmax; + if (this.zoom_xmin != this.zoom_xmax) { + this.scale_xmin = this.zoom_xmin; + this.scale_xmax = this.zoom_xmax; + } + if (this.x_kind == 'time') { + this.x = d3.time.scale(); + } else + if (this.swap_xy ? pad.fLogy : pad.fLogx) { + this.logx = true; + + if (this.scale_xmax <= 0) this.scale_xmax = 0; + + if ((this.scale_xmin <= 0) && (this.nbinsx>0)) + for (var i=0;i0) break; + } + + if ((this.scale_xmin <= 0) || (this.scale_xmin >= this.scale_xmax)) { + this.scale_xmin = this.scale_xmax * 0.0001; + } + + this.x = d3.scale.log(); + } else { + this.x = d3.scale.linear(); + } + + this.x.domain([this.ConvertX(this.scale_xmin), this.ConvertX(this.scale_xmax)]) + .range(this.swap_xy ? [ h, 0 ] : [ 0, w ]); + + if (this.x_kind == 'time') { + // we emulate scale functionality + this.grx = function(val) { return this.x(this.ConvertX(val)); } + } else + if (this.logx) { + this.grx = function(val) { return (val < this.scale_xmin) ? (this.swap_xy ? this.x.range()[0]+5 : -5) : this.x(val); } + } else { + this.grx = this.x; + } + + this.scale_ymin = this.ymin; + this.scale_ymax = this.ymax; + if (this.zoom_ymin != this.zoom_ymax) { + this.scale_ymin = this.zoom_ymin; + this.scale_ymax = this.zoom_ymax; + } + + if (this.histo.fYaxis.fTimeDisplay) { + this.y_kind = 'time'; + this.timeoffsety = JSROOT.Painter.getTimeOffset(this.histo.fYaxis); + this.ConvertY = function(y) { return new Date(this.timeoffsety + y*1000); }; + this.RevertY = function(gry) { return (this.y.invert(gry) - this.timeoffsety) / 1000; }; + } else { + this.y_kind = ((this.Dimension()==2) && (this.histo.fYaxis.fLabels!=null)) ? 'labels' : 'normal'; + this.ConvertY = function(y) { return y; }; + this.RevertY = function(gry) { return this.y.invert(gry); }; + } + + if (this.swap_xy ? pad.fLogx : pad.fLogy) { + this.logy = true; + if (this.scale_ymax <= 0) + this.scale_ymax = 1; + else + if ((this.zoom_ymin === this.zoom_ymax) && (this.Dimension()==1)) + this.scale_ymax*=1.8; + + if ((this.scale_ymin <= 0) && (this.nbinsy>0)) + for (var i=0;i0) break; + } + + if ((this.scale_ymin <= 0) && ('ymin_nz' in this) && (this.ymin_nz > 0)) + this.scale_ymin = 0.3*this.ymin_nz; + + if ((this.scale_ymin <= 0) || (this.scale_ymin >= this.scale_ymax)) + this.scale_ymin = 0.000001 * this.scale_ymax; + this.y = d3.scale.log(); + } else + if (this.y_kind=='time') { + this.y = d3.time.scale(); + } else { + this.y = d3.scale.linear() + } + + this.y.domain([ this.ConvertY(this.scale_ymin), this.ConvertY(this.scale_ymax) ]) + .range(this.swap_xy ? [ 0, w ] : [ h, 0 ]); + + if (this.y_kind=='time') { + // we emulate scale functionality + this.gry = function(val) { return this.y(this.ConvertY(val)); } + } else + if (this.logy) { + // make protecttion for log + this.gry = function(val) { return (val < this.scale_ymin) ? (this.swap_xy ? -5 : this.y.range()[0]+5) : this.y(val); } + } else { + this.gry = this.y; + } + } + + JSROOT.THistPainter.prototype.DrawGrids = function() { + // grid can only be drawn by first painter + if (!this.is_main_painter()) return; + + var layer = this.svg_frame().select(".grid_layer"); + + layer.selectAll(".xgrid").remove(); + layer.selectAll(".ygrid").remove(); + + var pad = this.root_pad(), h = this.frame_height(), w = this.frame_width(), grid; + + // add a grid on x axis, if the option is set + if (pad && pad.fGridx && this.x_handle) { + grid = ""; + for (var n=0;n 0) + layer.append("svg:path") + .attr("class", "xgrid") + .attr("d", grid) + .style("stroke", "black") + .style("stroke-width", 1) + .style("stroke-dasharray", JSROOT.Painter.root_line_styles[11]); + } + + // add a grid on y axis, if the option is set + if (pad && pad.fGridy && this.y_handle) { + grid = ""; + for (var n=0;n 0) + layer.append("svg:path") + .attr("class", "ygrid") + .attr("d", grid) + .style("stroke", "black") + .style("stroke-width", 1) + .style("stroke-dasharray", JSROOT.Painter.root_line_styles[11]); + } + } + + JSROOT.THistPainter.prototype.DrawBins = function() { + alert("HistPainter.DrawBins not implemented"); + } + + JSROOT.THistPainter.prototype.AxisAsText = function(axis, value) { + if (axis == "x") { + if (this.x_kind == 'time') + value = this.ConvertX(value); + + if (this.x_handle && ('format' in this.x_handle)) + return this.x_handle.format(value); + + return value.toPrecision(4); + } + + if (axis == "y") { + if (this.y_kind == 'time') + value = this.ConvertY(value); + + if (this.y_handle && ('format' in this.y_handle)) + return this.y_handle.format(value); + + return value.toPrecision(4); + } + + return value.toPrecision(4); + } + + JSROOT.THistPainter.prototype.DrawAxes = function(shrink_forbidden) { + // axes can be drawn only for main histogram + + if (!this.is_main_painter()) return; + + var layer = this.svg_frame().select(".axis_layer"), + w = this.frame_width(), + h = this.frame_height(), + pad = this.root_pad(); + + this.x_handle = new JSROOT.TAxisPainter(this.histo.fXaxis, true); + this.x_handle.SetDivId(this.divid, -1); + + this.x_handle.SetAxisConfig("xaxis", + (this.logx && (this.x_kind !== "time")) ? "log" : this.x_kind, + this.x, this.xmin, this.xmax, this.scale_xmin, this.scale_xmax); + + this.y_handle = new JSROOT.TAxisPainter(this.histo.fYaxis, true); + this.y_handle.SetDivId(this.divid, -1); + + this.y_handle.SetAxisConfig("yaxis", + (this.logy && this.y_kind !== "time") ? "log" : this.y_kind, + this.y, this.ymin, this.ymax, this.scale_ymin, this.scale_ymax); + + var draw_horiz = this.swap_xy ? this.y_handle : this.x_handle; + var draw_vertical = this.swap_xy ? this.x_handle : this.y_handle; + + draw_horiz.DrawAxis(false, layer, w, h, "translate(0," + h + ")", false, pad.fTickx ? -h : 0); + draw_vertical.DrawAxis(true, layer, w, h, undefined, false, pad.fTicky ? w : 0); + + if (shrink_forbidden) return; + + var shrink = 0., ypos = draw_vertical.position; + + if ((-0.2*w < ypos) && (ypos < 0)) { + shrink = -ypos/w + 0.001; + this.shrink_frame_left += shrink; + } else + if ((ypos>0) && (ypos<0.3*w) && (this.shrink_frame_left > 0) && (ypos/w > this.shrink_frame_left)) { + shrink = -this.shrink_frame_left; + this.shrink_frame_left = 0.; + } + + if (shrink != 0) { + this.frame_painter().Shrink(shrink, 0); + this.frame_painter().Redraw(); + this.CreateXY(); + this.DrawAxes(true); + } + } + + JSROOT.THistPainter.prototype.DrawTitle = function() { + + // case when histogram drawn over other histogram (same option) + if (!this.is_main_painter()) return; + + var tpainter = this.FindPainterFor(null, "title"); + var pavetext = (tpainter !== null) ? tpainter.GetObject() : null; + if (pavetext === null) pavetext = this.FindInPrimitives("title"); + if ((pavetext !== null) && (pavetext._typename !== "TPaveText")) pavetext = null; + + var draw_title = !this.histo.TestBit(JSROOT.TH1StatusBits.kNoTitle); + + if (pavetext !== null) { + pavetext.Clear(); + if (draw_title) + pavetext.AddText(this.histo.fTitle); + } else + if (draw_title && !tpainter && (this.histo.fTitle.length > 0)) { + pavetext = JSROOT.Create("TPaveText"); + + JSROOT.extend(pavetext, { fName: "title", fX1NDC: 0.28, fY1NDC: 0.94, fX2NDC: 0.72, fY2NDC: 0.99 } ); + pavetext.AddText(this.histo.fTitle); + + JSROOT.Painter.drawPaveText(this.divid, pavetext); + } + } + + JSROOT.THistPainter.prototype.ToggleStat = function(arg) { + + var stat = this.FindStat(), statpainter = null; + + if (stat == null) { + if (arg=='only-check') return false; + // when statbox created first time, one need to draw it + stat = this.CreateStat(); + } else { + statpainter = this.FindPainterFor(stat); + } + + if (arg=='only-check') return statpainter ? statpainter.Enabled : false; + + if (statpainter) { + statpainter.Enabled = !statpainter.Enabled; + // when stat box is drawed, it always can be draw individualy while it + // should be last for colz RedrawPad is used + statpainter.Redraw(); + return statpainter.Enabled; + } + + JSROOT.draw(this.divid, stat, "onpad:" + this.pad_name); + + return true; + } + + JSROOT.THistPainter.prototype.IsAxisZoomed = function(axis) { + var obj = this.main_painter(); + if (obj == null) obj = this; + if (axis === "x") return obj.zoom_xmin != obj.zoom_xmax; + if (axis === "y") return obj.zoom_ymin != obj.zoom_ymax; + return false; + } + + JSROOT.THistPainter.prototype.GetSelectIndex = function(axis, size, add) { + // be aware - here indexs starts from 0 + var indx = 0, obj = this.main_painter(); + if (obj == null) obj = this; + var nbin = this['nbins'+axis]; + if (!nbin) nbin = 0; + if (!add) add = 0; + + var func = 'GetIndex' + axis.toUpperCase(), + min = obj['zoom_' + axis + 'min'], + max = obj['zoom_' + axis + 'max']; + + if ((min != max) && (func in this)) { + if (size == "left") { + indx = this[func](min, add); + } else { + indx = this[func](max, add + 0.5); + } + } else { + indx = (size == "left") ? 0 : nbin; + } + + var taxis; // TAxis object of histogram, where user range can be stored + if (this.histo) taxis = this.histo["f" + axis.toUpperCase() + "axis"]; + if (taxis) { + if ((taxis.fFirst === taxis.fLast) || !taxis.TestBit(JSROOT.EAxisBits.kAxisRange) || + ((taxis.fFirst<=1) && (taxis.fLast>=nbin))) taxis = undefined; + } + + if (size == "left") { + if (indx < 0) indx = 0; + if (taxis && (taxis.fFirst>1) && (indx nbin) indx = nbin; + if (taxis && (taxis.fLast <= nbin) && (indx>taxis.fLast)) indx = taxis.fLast; + } + + return indx; + } + + JSROOT.THistPainter.prototype.FindStat = function() { + if (this.histo.fFunctions !== null) + for (var i = 0; i < this.histo.fFunctions.arr.length; ++i) { + var func = this.histo.fFunctions.arr[i]; + + if ((func._typename == 'TPaveStats') && + (func.fName == 'stats')) return func; + } + + return null; + } + + JSROOT.THistPainter.prototype.CreateStat = function() { + + if (!this.draw_content) return null; + + var stats = this.FindStat(); + if (stats != null) return stats; + + stats = JSROOT.Create('TPaveStats'); + JSROOT.extend(stats, { fName : 'stats', + fOptStat: JSROOT.gStyle.OptStat, + fOptFit: JSROOT.gStyle.OptFit, + fBorderSize : 1} ); + JSROOT.extend(stats, JSROOT.gStyle.StatNDC); + JSROOT.extend(stats, JSROOT.gStyle.StatText); + JSROOT.extend(stats, JSROOT.gStyle.StatFill); + + if (this.histo._typename.match(/^TProfile/) || this.histo._typename.match(/^TH2/)) + stats.fY1NDC = 0.67; + + stats.AddText(this.histo.fName); + + if (this.histo.fFunctions === null) + this.histo.fFunctions = JSROOT.Create("TList"); + + this.histo.fFunctions.Add(stats,""); + + return stats; + } + + JSROOT.THistPainter.prototype.AddFunction = function(obj, asfirst) { + var histo = this.GetObject(); + if (!histo || !obj) return; + + if (histo.fFunctions == null) + histo.fFunctions = JSROOT.Create("TList"); + + if (asfirst) + histo.fFunctions.AddFirst(obj); + else + histo.fFunctions.Add(obj); + + } + + JSROOT.THistPainter.prototype.FindFunction = function(type_name) { + var funcs = this.GetObject().fFunctions; + if (funcs === null) return null; + + for (var i = 0; i < funcs.arr.length; ++i) + if (funcs.arr[i]._typename === type_name) return funcs.arr[i]; + + return null; + } + + JSROOT.THistPainter.prototype.DrawNextFunction = function(indx, callback) { + // method draws next function from the functions list + + if (this.options.Same || (this.histo.fFunctions === null) || (indx >= this.histo.fFunctions.arr.length)) + return JSROOT.CallBack(callback); + + var func = this.histo.fFunctions.arr[indx], + opt = this.histo.fFunctions.opt[indx], + do_draw = false, + func_painter = this.FindPainterFor(func); + + // no need to do something if painter for object was already done + // object will be redraw automatically + if (func_painter === null) { + if (func._typename === 'TPaveText' || func._typename === 'TPaveStats') { + do_draw = !this.histo.TestBit(JSROOT.TH1StatusBits.kNoStats) && (this.options.NoStat!=1); + } else + if (func._typename === 'TF1') { + do_draw = !func.TestBit(JSROOT.BIT(9)); + } else + do_draw = (func._typename !== "TPaletteAxis"); + } + //if (('CompleteDraw' in func_painter) && (typeof func_painter.CompleteDraw == 'function')) + // func_painter.CompleteDraw(); + + if (do_draw) { + var painter = JSROOT.draw(this.divid, func, opt); + if (painter) return painter.WhenReady(this.DrawNextFunction.bind(this, indx+1, callback)); + } + + this.DrawNextFunction(indx+1, callback); + } + + JSROOT.THistPainter.prototype.UnzoomUserRange = function(dox, doy, doz) { + + if (!this.histo) return false; + + function UnzoomTAxis(obj) { + if (!obj) return false; + if (!obj.TestBit(JSROOT.EAxisBits.kAxisRange)) return false; + if (obj.fFirst === obj.fLast) return false; + if ((obj.fFirst <= 1) && (obj.fLast >= obj.fNbins)) return false; + obj.InvertBit(JSROOT.EAxisBits.kAxisRange); + return true; + } + + var res = false; + + if (dox) res |= UnzoomTAxis(this.histo.fXaxis); + if (doy) res |= UnzoomTAxis(this.histo.fYaxis); + if (doz) res |= UnzoomTAxis(this.histo.fZaxis); + + return res; + } + + JSROOT.THistPainter.prototype.ToggleLog = function(axis) { + var obj = this.main_painter(), pad = this.root_pad(); + if (!obj) obj = this; + var curr = pad["fLog" + axis]; + // do not allow log scale for labels + if (!curr && (this[axis+"_kind"] == "labels")) return; + pad["fLog" + axis] = curr ? 0 : 1; + obj.RedrawPad(); + } + + JSROOT.THistPainter.prototype.Zoom = function(xmin, xmax, ymin, ymax, zmin, zmax) { + // function can be used for zooming into specified range + // if both ranges for axis 0 (like xmin==xmax==0), axis will be unzoomed + + var main = this.main_painter(), + zoom_x = (xmin !== xmax), zoom_y = (ymin !== ymax), zoom_z = (zmin !== zmax), + unzoom_x = false, unzoom_y = false, unzoom_z = false; + + if (zoom_x) { + var cnt = 0; + if (xmin <= main.xmin) { xmin = main.xmin; cnt++; } + if (xmax >= main.xmax) { xmax = main.xmax; cnt++; } + if (cnt === 2) { zoom_x = false; unzoom_x = true; } + } else { + unzoom_x = (xmin === xmax) && (xmin === 0); + } + + if (zoom_y) { + var cnt = 0; + if (ymin <= main.ymin) { ymin = main.ymin; cnt++; } + if (ymax >= main.ymax) { ymax = main.ymax; cnt++; } + if (cnt === 2) { zoom_y = false; unzoom_y = true; } + } else { + unzoom_y = (ymin === ymax) && (ymin === 0); + } + + if (zoom_z) { + var cnt = 0; + if (zmin <= main.zmin) { zmin = main.zmin; cnt++; } + if (zmax >= main.zmax) { zmax = main.zmax; cnt++; } + if (cnt === 2) { zoom_z = false; unzoom_z = true; } + } else { + unzoom_z = (zmin === zmax) && (zmin === 0); + } + + var changed = false; + + // first process zooming (if any) + if (zoom_x || zoom_y || zoom_z) + main.ForEachPainter(function(obj) { + if (zoom_x && obj.CanZoomIn("x", xmin, xmax)) { + main.zoom_xmin = xmin; + main.zoom_xmax = xmax; + changed = true; + zoom_x = false; + } + if (zoom_y && obj.CanZoomIn("y", ymin, ymax)) { + main.zoom_ymin = ymin; + main.zoom_ymax = ymax; + changed = true; + zoom_y = false; + } + if (zoom_z && obj.CanZoomIn("z", zmin, zmax)) { + main.zoom_zmin = zmin; + main.zoom_zmax = zmax; + changed = true; + zoom_z = false; + } + }); + + // and process unzoom, if any + if (unzoom_x || unzoom_y || unzoom_z) { + if (unzoom_x) { + if (main.zoom_xmin !== main.zoom_xmax) changed = true; + main.zoom_xmin = main.zoom_xmax = 0; + } + if (unzoom_y) { + if (main.zoom_ymin !== main.zoom_ymax) changed = true; + main.zoom_ymin = main.zoom_ymax = 0; + } + if (unzoom_z) { + if (main.zoom_zmin !== main.zoom_zmax) changed = true; + main.zoom_zmin = main.zoom_zmax = 0; + } + + // first try to unzoom main painter - it could have user range specified + if (!changed) { + changed = main.UnzoomUserRange(unzoom_x, unzoom_y, unzoom_z); + + // than try to unzoom all overlapped objects + var pp = this.pad_painter(true); + if (pp && pp.painters) + pp.painters.forEach(function(paint){ + if (paint && (paint!==main) && (typeof paint.UnzoomUserRange == 'function')) + if (paint.UnzoomUserRange(unzoom_x, unzoom_y, unzoom_z)) changed = true; + }); + } + } + + if (changed) this.RedrawPad(); + + return changed; + } + + JSROOT.THistPainter.prototype.Unzoom = function(dox, doy, doz) { + if (typeof dox === 'undefined') { dox = true; doy = true; doz = true; } else + if (typeof dox === 'string') { doz = dox.indexOf("z")>=0; doy = dox.indexOf("y")>=0; dox = dox.indexOf("x")>=0; } + + if (dox || doy || dox) this.zoom_changed_interactive = true; + + return this.Zoom(dox ? 0 : undefined, dox ? 0 : undefined, + doy ? 0 : undefined, doy ? 0 : undefined, + doz ? 0 : undefined, doz ? 0 : undefined); + } + + JSROOT.THistPainter.prototype.clearInteractiveElements = function() { + JSROOT.Painter.closeMenu(); + if (this.zoom_rect != null) { this.zoom_rect.remove(); this.zoom_rect = null; } + this.zoom_kind = 0; + + // enable tooltip in frame painter + this.SwitchTooltip(true); + } + + JSROOT.THistPainter.prototype.mouseDoubleClick = function() { + d3.event.preventDefault(); + var m = d3.mouse(this.svg_frame().node()); + this.clearInteractiveElements(); + var kind = "xyz"; + if (m[0] < 0) kind = "y"; else + if (m[1] > this.frame_height()) kind = "x"; + this.Unzoom(kind); + } + + JSROOT.THistPainter.prototype.startRectSel = function() { + // ignore when touch selection is actiavated + + if (this.zoom_kind > 100) return; + + // ignore all events from non-left button + if ((d3.event.which || d3.event.button) !== 1) return; + + d3.event.preventDefault(); + + this.clearInteractiveElements(); + this.zoom_origin = d3.mouse(this.svg_frame().node()); + + this.zoom_curr = [ Math.max(0, Math.min(this.frame_width(), this.zoom_origin[0])), + Math.max(0, Math.min(this.frame_height(), this.zoom_origin[1])) ]; + + if (this.zoom_origin[0] < 0) { + this.zoom_kind = 3; // only y + this.zoom_origin[0] = 0; + this.zoom_origin[1] = this.zoom_curr[1]; + this.zoom_curr[0] = this.frame_width(); + this.zoom_curr[1] += 1; + } else if (this.zoom_origin[1] > this.frame_height()) { + this.zoom_kind = 2; // only x + this.zoom_origin[0] = this.zoom_curr[0]; + this.zoom_origin[1] = 0; + this.zoom_curr[0] += 1; + this.zoom_curr[1] = this.frame_height(); + } else { + this.zoom_kind = 1; // x and y + this.zoom_origin[0] = this.zoom_curr[0]; + this.zoom_origin[1] = this.zoom_curr[1]; + } + + d3.select(window).on("mousemove.zoomRect", this.moveRectSel.bind(this)) + .on("mouseup.zoomRect", this.endRectSel.bind(this), true); + + this.zoom_rect = null; + + // disable tooltips in frame painter + this.SwitchTooltip(false); + + d3.event.stopPropagation(); + } + + JSROOT.THistPainter.prototype.moveRectSel = function() { + + if ((this.zoom_kind == 0) || (this.zoom_kind > 100)) return; + + d3.event.preventDefault(); + var m = d3.mouse(this.svg_frame().node()); + + m[0] = Math.max(0, Math.min(this.frame_width(), m[0])); + m[1] = Math.max(0, Math.min(this.frame_height(), m[1])); + + switch (this.zoom_kind) { + case 1: this.zoom_curr[0] = m[0]; this.zoom_curr[1] = m[1]; break; + case 2: this.zoom_curr[0] = m[0]; break; + case 3: this.zoom_curr[1] = m[1]; break; + } + + if (this.zoom_rect===null) + this.zoom_rect = this.svg_frame() + .append("rect") + .attr("class", "zoom") + .attr("pointer-events","none"); + + this.zoom_rect.attr("x", Math.min(this.zoom_origin[0], this.zoom_curr[0])) + .attr("y", Math.min(this.zoom_origin[1], this.zoom_curr[1])) + .attr("width", Math.abs(this.zoom_curr[0] - this.zoom_origin[0])) + .attr("height", Math.abs(this.zoom_curr[1] - this.zoom_origin[1])); + } + + JSROOT.THistPainter.prototype.endRectSel = function() { + if ((this.zoom_kind == 0) || (this.zoom_kind > 100)) return; + + d3.event.preventDefault(); + + d3.select(window).on("mousemove.zoomRect", null) + .on("mouseup.zoomRect", null); + + var m = d3.mouse(this.svg_frame().node()); + + m[0] = Math.max(0, Math.min(this.frame_width(), m[0])); + m[1] = Math.max(0, Math.min(this.frame_height(), m[1])); + + var changed = [true, true]; + + switch (this.zoom_kind) { + case 1: this.zoom_curr[0] = m[0]; this.zoom_curr[1] = m[1]; break; + case 2: this.zoom_curr[0] = m[0]; changed[1] = false; break; // only X + case 3: this.zoom_curr[1] = m[1]; changed[0] = false; break; // only Y + } + + var xmin, xmax, ymin, ymax, isany = false, + idx = this.swap_xy ? 1 : 0, idy = 1 - idx; + + if (changed[idx] && (Math.abs(this.zoom_curr[idx] - this.zoom_origin[idx]) > 10)) { + xmin = Math.min(this.RevertX(this.zoom_origin[idx]), this.RevertX(this.zoom_curr[idx])); + xmax = Math.max(this.RevertX(this.zoom_origin[idx]), this.RevertX(this.zoom_curr[idx])); + isany = true; + } + + if (changed[idy] && (Math.abs(this.zoom_curr[idy] - this.zoom_origin[idy]) > 10)) { + ymin = Math.min(this.RevertY(this.zoom_origin[idy]), this.RevertY(this.zoom_curr[idy])); + ymax = Math.max(this.RevertY(this.zoom_origin[idy]), this.RevertY(this.zoom_curr[idy])); + isany = true; + } + + this.clearInteractiveElements(); + + if (isany) { + this.zoom_changed_interactive = true; + this.Zoom(xmin, xmax, ymin, ymax); + } + } + + JSROOT.THistPainter.prototype.startTouchZoom = function() { + // in case when zooming was started, block any other kind of events + if (this.zoom_kind != 0) { + d3.event.preventDefault(); + d3.event.stopPropagation(); + return; + } + + var arr = d3.touches(this.svg_frame().node()); + this.touch_cnt+=1; + + // normally double-touch will be handled + // touch with single click used for context menu + if (arr.length == 1) { + // this is touch with single element + + var now = new Date(); + var diff = now.getTime() - this.last_touch.getTime(); + this.last_touch = now; + + if ((diff < 300) && (this.zoom_curr != null) + && (Math.abs(this.zoom_curr[0] - arr[0][0]) < 30) + && (Math.abs(this.zoom_curr[1] - arr[0][1]) < 30)) { + + d3.event.preventDefault(); + d3.event.stopPropagation(); + + this.clearInteractiveElements(); + this.Unzoom("xyz"); + + this.last_touch = new Date(0); + + this.svg_frame().on("touchcancel", null) + .on("touchend", null, true); + } else + if (JSROOT.gStyle.ContextMenu) { + this.zoom_curr = arr[0]; + this.svg_frame().on("touchcancel", this.endTouchSel.bind(this)) + .on("touchend", this.endTouchSel.bind(this)); + d3.event.preventDefault(); + d3.event.stopPropagation(); + } + } + + if (arr.length != 2) return; + + d3.event.preventDefault(); + d3.event.stopPropagation(); + + this.clearInteractiveElements(); + + this.svg_frame().on("touchcancel", null) + .on("touchend", null); + + var pnt1 = arr[0], pnt2 = arr[1]; + + this.zoom_curr = [ Math.min(pnt1[0], pnt2[0]), Math.min(pnt1[1], pnt2[1]) ]; + this.zoom_origin = [ Math.max(pnt1[0], pnt2[0]), Math.max(pnt1[1], pnt2[1]) ]; + + if (this.zoom_curr[0] < 0) { + this.zoom_kind = 103; // only y + this.zoom_curr[0] = 0; + this.zoom_origin[0] = this.frame_width(); + } else if (this.zoom_origin[1] > this.frame_height()) { + this.zoom_kind = 102; // only x + this.zoom_curr[1] = 0; + this.zoom_origin[1] = this.frame_height(); + } else { + this.zoom_kind = 101; // x and y + } + + this.SwitchTooltip(false); + + this.zoom_rect = this.svg_frame().append("rect") + .attr("class", "zoom") + .attr("id", "zoomRect") + .attr("x", this.zoom_curr[0]) + .attr("y", this.zoom_curr[1]) + .attr("width", this.zoom_origin[0] - this.zoom_curr[0]) + .attr("height", this.zoom_origin[1] - this.zoom_curr[1]); + + d3.select(window).on("touchmove.zoomRect", this.moveTouchSel.bind(this)) + .on("touchcancel.zoomRect", this.endTouchSel.bind(this)) + .on("touchend.zoomRect", this.endTouchSel.bind(this)); + } + + JSROOT.THistPainter.prototype.moveTouchSel = function() { + if (this.zoom_kind < 100) return; + + d3.event.preventDefault(); + + var arr = d3.touches(this.svg_frame().node()); + + if (arr.length != 2) + return this.clearInteractiveElements(); + + var pnt1 = arr[0], pnt2 = arr[1]; + + if (this.zoom_kind != 103) { + this.zoom_curr[0] = Math.min(pnt1[0], pnt2[0]); + this.zoom_origin[0] = Math.max(pnt1[0], pnt2[0]); + } + if (this.zoom_kind != 102) { + this.zoom_curr[1] = Math.min(pnt1[1], pnt2[1]); + this.zoom_origin[1] = Math.max(pnt1[1], pnt2[1]); + } + + this.zoom_rect.attr("x", this.zoom_curr[0]) + .attr("y", this.zoom_curr[1]) + .attr("width", this.zoom_origin[0] - this.zoom_curr[0]) + .attr("height", this.zoom_origin[1] - this.zoom_curr[1]); + + if ((this.zoom_origin[0] - this.zoom_curr[0] > 10) + || (this.zoom_origin[1] - this.zoom_curr[1] > 10)) + this.SwitchTooltip(false); + + d3.event.stopPropagation(); + } + + JSROOT.THistPainter.prototype.endTouchSel = function() { + + this.svg_frame().on("touchcancel", null) + .on("touchend", null); + + if (this.zoom_kind === 0) { + // special case - single touch can ends up with context menu + + d3.event.preventDefault(); + + var now = new Date(); + + var diff = now.getTime() - this.last_touch.getTime(); + + if ((diff > 500) && (diff<2000) && !this.frame_painter().IsTooltipShown()) { + this.ShowContextMenu('main', { clientX: this.zoom_curr[0], clientY: this.zoom_curr[1] }); + this.last_touch = new Date(0); + } else { + this.clearInteractiveElements(); + } + } + + if (this.zoom_kind < 100) return; + + d3.event.preventDefault(); + d3.select(window).on("touchmove.zoomRect", null) + .on("touchend.zoomRect", null) + .on("touchcancel.zoomRect", null); + + var xmin, xmax, ymin, ymax, isany = false, + xid = this.swap_xy ? 1 : 0, yid = 1 - xid, + changed = [true, true]; + if (this.zoom_kind === 102) changed[1] = false; + if (this.zoom_kind === 103) changed[0] = false; + + if (changed[xid] && (Math.abs(this.zoom_curr[xid] - this.zoom_origin[xid]) > 10)) { + xmin = Math.min(this.RevertX(this.zoom_origin[xid]), this.RevertX(this.zoom_curr[xid])); + xmax = Math.max(this.RevertX(this.zoom_origin[xid]), this.RevertX(this.zoom_curr[xid])); + isany = true; + } + + if (changed[yid] && (Math.abs(this.zoom_curr[yid] - this.zoom_origin[yid]) > 10)) { + ymin = Math.min(this.RevertY(this.zoom_origin[yid]), this.RevertY(this.zoom_curr[yid])); + ymax = Math.max(this.RevertY(this.zoom_origin[yid]), this.RevertY(this.zoom_curr[yid])); + isany = true; + } + + this.clearInteractiveElements(); + this.last_touch = new Date(0); + + if (isany) { + this.zoom_changed_interactive = true; + this.Zoom(xmin, xmax, ymin, ymax); + } + + d3.event.stopPropagation(); + } + + JSROOT.THistPainter.prototype.mouseWheel = function() { + d3.event.stopPropagation(); + + var delta = 0; + switch (d3.event.deltaMode) { + case 0: delta = d3.event.deltaY / this.pad_height() * 2; break; // DOM_DELTA_PIXEL + case 1: delta = d3.event.deltaY / this.pad_height() * 40; break; // DOM_DELTA_LINE + case 2: delta = d3.event.deltaY / this.pad_height() * 200; break; // DOM_DELTA_PAGE + } + if (delta===0) return; + + d3.event.preventDefault(); + + this.clearInteractiveElements(); + + if (delta < -0.2) delta = -0.2; else if (delta>0.2) delta = 0.2; + + var itemx = { name: "x", ignore: false }, + itemy = { name: "y", ignore: (this.Dimension() == 1) }, + cur = d3.mouse(this.svg_frame().node()), + painter = this; + + function ProcessAxis(item, dmin, ignore) { + item.min = item.max = undefined; + item.changed = false; + if (ignore && item.ignore) return; + + item.min = painter["scale_" + item.name+"min"]; + item.max = painter["scale_" + item.name+"max"]; + if ((item.min === item.max) && (delta<0)) { + item.min = painter[item.name+"min"]; + item.max = painter[item.name+"max"]; + } + + if (item.min >= item.max) return; + + if ((dmin>0) && (dmin<1)) { + if (painter['log'+item.name]) { + var factor = (item.min>0) ? JSROOT.log10(item.max/item.min) : 2; + if (factor>10) factor = 10; else if (factor<1.5) factor = 1.5; + item.min = item.min / Math.pow(factor, delta*dmin); + item.max = item.max * Math.pow(factor, delta*(1-dmin)); + } else { + var rx = (item.max - item.min); + if (delta>0) rx = 1.001 * rx / (1-delta); + item.min += -delta*dmin*rx; + item.max -= -delta*(1-dmin)*rx; + } + if (item.min >= item.max) item.min = item.max = undefined; + } else { + item.min = item.max = undefined; + } + + item.changed = ((item.min !== undefined) && (item.max !== undefined)); + } + + ProcessAxis(this.swap_xy ? itemy : itemx, cur[0] / this.frame_width(), (cur[1] <= this.frame_height())); + + ProcessAxis(this.swap_xy ? itemx : itemy, 1 - cur[1] / this.frame_height(), (cur[0] >= 0)); + + this.Zoom(itemx.min, itemx.max, itemy.min, itemy.max); + + if (itemx.changed || itemy.changed) this.zoom_changed_interactive = true; + } + + JSROOT.THistPainter.prototype.AddInteractive = function() { + // only first painter in list allowed to add interactive functionality to the frame + + if ((!JSROOT.gStyle.Zooming && !JSROOT.gStyle.ContextMenu) || !this.is_main_painter()) return; + + var svg = this.svg_frame(); + + if (svg.empty() || svg.property('interactive_set')) return; + + this.last_touch = new Date(0); + this.zoom_kind = 0; // 0 - none, 1 - XY, 2 - only X, 3 - only Y, (+100 for touches) + this.zoom_rect = null; + this.zoom_origin = null; // original point where zooming started + this.zoom_curr = null; // current point for zomming + this.touch_cnt = 0; + + if (JSROOT.gStyle.Zooming) { + svg.on("mousedown", this.startRectSel.bind(this) ); + svg.on("dblclick", this.mouseDoubleClick.bind(this) ); + svg.on("wheel", this.mouseWheel.bind(this) ); + } + + if (JSROOT.touches && (JSROOT.gStyle.Zooming || JSROOT.gStyle.ContextMenu)) + svg.on("touchstart", this.startTouchZoom.bind(this) ); + + if (JSROOT.gStyle.ContextMenu) { + if (JSROOT.touches) { + svg.selectAll(".xaxis_container") + .on("touchstart", this.startTouchMenu.bind(this,"x") ); + svg.selectAll(".yaxis_container") + .on("touchstart", this.startTouchMenu.bind(this,"y") ); + } + svg.on("contextmenu", this.ShowContextMenu.bind(this) ); + svg.selectAll(".xaxis_container") + .on("contextmenu", this.ShowContextMenu.bind(this,"x")); + svg.selectAll(".yaxis_container") + .on("contextmenu", this.ShowContextMenu.bind(this,"y")); + } + + svg.property('interactive_set', true); + } + + JSROOT.THistPainter.prototype.ShowContextMenu = function(kind, evnt, obj) { + // ignore context menu when touches zooming is ongoing + if (('zoom_kind' in this) && (this.zoom_kind > 100)) return; + + // this is for debug purposes only, when context menu is where, close is and show normal menu + //if (!evnt && !kind && document.getElementById('root_ctx_menu')) { + // var elem = document.getElementById('root_ctx_menu'); + // elem.parentNode.removeChild(elem); + // return; + //} + + var menu_painter = this, frame_corner = false; // object used to show context menu + + if (!evnt) { + d3.event.preventDefault(); + d3.event.stopPropagation(); // disable main context menu + evnt = d3.event; + + if (kind === undefined) { + var ms = d3.mouse(this.svg_frame().node()); + var tch = d3.touches(this.svg_frame().node()); + var pnt = null, pp = this.pad_painter(true), fp = this.frame_painter(), sel = null; + + if (tch.length === 1) pnt = { x: tch[0][0], y: tch[0][1], touch: true }; else + if (ms.length === 2) pnt = { x: ms[0], y: ms[1], touch: false }; + + if ((pnt !== null) && (pp !== null)) { + pnt.painters = true; // assign painter for every tooltip + var hints = pp.GetTooltips(pnt); + + var bestdist = 1000; + for (var n=0;n0) && (pnt.x<20) && (pnt.y>0) && (pnt.y<20); + } + } + + // one need to copy event, while after call back event may be changed + menu_painter.ctx_menu_evnt = evnt; + + JSROOT.Painter.createMenu(function(menu) { + menu.painter = this; // in all menu callbacks painter will be 'this' pointer + var domenu = this.FillContextMenu(menu, kind, obj); + + // fill frame menu by default - or append frame elements when actiavted in the frame corner + if (fp && (!domenu || (frame_corner && (kind!=="frame")))) + domenu = fp.FillContextMenu(menu); + + if (domenu) { + // suppress any running zomming + this.SwitchTooltip(false); + menu.show(this.ctx_menu_evnt, this.SwitchTooltip.bind(this, true) ); + } + + delete this.ctx_menu_evnt; // delete temporary variable + }.bind(menu_painter) ); // end menu creation + } + + + JSROOT.THistPainter.prototype.ChangeUserRange = function(arg) { + var taxis = this.histo['f'+arg+"axis"]; + if (!taxis) return; + + var curr = "[1," + taxis.fNbins+"]"; + if (taxis.TestBit(JSROOT.EAxisBits.kAxisRange)) + curr = "[" +taxis.fFirst+"," + taxis.fLast+"]"; + + var res = prompt("Enter user range for axis " + arg + " like [1," + taxis.fNbins + "]", curr); + if (res==null) return; + res = JSON.parse(res); + + if (!res || (res.length!=2) || isNaN(res[0]) || isNaN(res[1])) return; + taxis.fFirst = parseInt(res[0]); + taxis.fLast = parseInt(res[1]); + + var newflag = (taxis.fFirst < taxis.fLast) && (taxis.fFirst >= 1) && (taxis.fLast<=taxis.fNbins); + if (newflag != taxis.TestBit(JSROOT.EAxisBits.kAxisRange)) + taxis.InvertBit(JSROOT.EAxisBits.kAxisRange); + + this.Redraw(); + } + + JSROOT.THistPainter.prototype.FillContextMenu = function(menu, kind, obj) { + + // when fill and show context menu, remove all zooming + this.clearInteractiveElements(); + + if ((kind=="x") || (kind=="y") || (kind=="z")) { + var faxis = this.histo.fXaxis; + if (kind=="y") faxis = this.histo.fYaxis; else + if (kind=="z") faxis = obj ? obj : this.histo.fZaxis; + menu.add("header: " + kind.toUpperCase() + " axis"); + menu.add("Unzoom", this.Unzoom.bind(this, kind)); + menu.addchk(this.options["Log" + kind], "SetLog"+kind, this.ToggleLog.bind(this, kind) ); + menu.addchk(faxis.TestBit(JSROOT.EAxisBits.kMoreLogLabels), "More log", + function() { faxis.InvertBit(JSROOT.EAxisBits.kMoreLogLabels); this.RedrawPad(); }); + menu.addchk(faxis.TestBit(JSROOT.EAxisBits.kNoExponent), "No exponent", + function() { faxis.InvertBit(JSROOT.EAxisBits.kNoExponent); this.RedrawPad(); }); + + if ((kind === "z") && (this.options.Zscale > 0)) + if (this.FillPaletteMenu) this.FillPaletteMenu(menu); + + if (faxis != null) { + menu.add("sub:Labels"); + menu.addchk(faxis.TestBit(JSROOT.EAxisBits.kCenterLabels), "Center", + function() { faxis.InvertBit(JSROOT.EAxisBits.kCenterLabels); this.RedrawPad(); }); + this.AddColorMenuEntry(menu, "Color", faxis.fLabelColor, + function(arg) { faxis.fLabelColor = parseInt(arg); this.RedrawPad(); }); + this.AddSizeMenuEntry(menu,"Offset", 0, 0.1, 0.01, faxis.fLabelOffset, + function(arg) { faxis.fLabelOffset = parseFloat(arg); this.RedrawPad(); } ); + this.AddSizeMenuEntry(menu,"Size", 0.02, 0.11, 0.01, faxis.fLabelSize, + function(arg) { faxis.fLabelSize = parseFloat(arg); this.RedrawPad(); } ); + menu.add("endsub:"); + menu.add("sub:Title"); + menu.add("SetTitle", function() { + var t = prompt("Enter axis title", faxis.fTitle); + if (t!==null) { faxis.fTitle = t; this.RedrawPad(); } + }); + menu.addchk(faxis.TestBit(JSROOT.EAxisBits.kCenterTitle), "Center", + function() { faxis.InvertBit(JSROOT.EAxisBits.kCenterTitle); this.RedrawPad(); }); + menu.addchk(faxis.TestBit(JSROOT.EAxisBits.kRotateTitle), "Rotate", + function() { faxis.InvertBit(JSROOT.EAxisBits.kRotateTitle); this.RedrawPad(); }); + this.AddColorMenuEntry(menu, "Color", faxis.fTitleColor, + function(arg) { faxis.fTitleColor = parseInt(arg); this.RedrawPad(); }); + this.AddSizeMenuEntry(menu,"Offset", 0, 3, 0.2, faxis.fTitleOffset, + function(arg) { faxis.fTitleOffset = parseFloat(arg); this.RedrawPad(); } ); + this.AddSizeMenuEntry(menu,"Size", 0.02, 0.11, 0.01, faxis.fTitleSize, + function(arg) { faxis.fTitleSize = parseFloat(arg); this.RedrawPad(); } ); + menu.add("endsub:"); + } + menu.add("sub:Ticks"); + this.AddColorMenuEntry(menu, "Color", faxis.fLineColor, + function(arg) { faxis.fLineColor = parseInt(arg); this.RedrawPad(); }); + this.AddColorMenuEntry(menu, "Color", faxis.fAxisColor, + function(arg) { faxis.fAxisColor = parseInt(arg); this.RedrawPad(); }); + this.AddSizeMenuEntry(menu,"Size", -0.05, 0.055, 0.01, faxis.fTickLength, + function(arg) { faxis.fTickLength = parseFloat(arg); this.RedrawPad(); } ); + menu.add("endsub:"); + return true; + } + + if (kind == "frame") { + var fp = this.frame_painter(); + if (fp) return fp.FillContextMenu(menu); + } + + menu.add("header:"+ this.histo._typename + "::" + this.histo.fName); + + if (this.draw_content) { + menu.addchk(this.ToggleStat('only-check'), "Show statbox", function() { this.ToggleStat(); }); + if (this.Dimension() == 1) { + menu.add("User range X", "X", this.ChangeUserRange); + } else { + menu.add("sub:User ranges"); + menu.add("X", "X", this.ChangeUserRange); + menu.add("Y", "Y", this.ChangeUserRange); + if (this.Dimension() > 2) + menu.add("Z", "Z", this.ChangeUserRange); + menu.add("endsub:") + } + + if (typeof this.FillHistContextMenu == 'function') + this.FillHistContextMenu(menu); + } + + if ((this.options.Lego > 0) || (this.Dimension() === 3)) { + // menu for 3D drawings + + if (menu.size() > 0) + menu.add("separator"); + + menu.addchk(this.enable_tooltip, 'Show tooltips', function() { + this.enable_tooltip = !this.enable_tooltip; + }); + + if (this.enable_tooltip) + menu.addchk(this.enable_hightlight, 'Hightlight bins', function() { + this.enable_hightlight = !this.enable_hightlight; + if (!this.enable_hightlight && this.BinHighlight3D) this.BinHighlight3D(null); + }); + + menu.addchk(this.options.FrontBox, 'Front box', function() { + this.options.FrontBox = !this.options.FrontBox; + if (this.Render3D) this.Render3D(); + }); + menu.addchk(this.options.BackBox, 'Back box', function() { + this.options.BackBox = !this.options.BackBox; + if (this.Render3D) this.Render3D(); + }); + + + if (this.draw_content) { + menu.addchk(this.options.Zero, 'Suppress zeros', function() { + this.options.Zero = !this.options.Zero; + this.RedrawPad(); + }); + + if ((this.options.Lego==12) || (this.options.Lego==14)) { + menu.addchk(this.options.Zscale, "Z scale", function() { + this.ToggleColz(); + }); + if (this.FillPaletteMenu) this.FillPaletteMenu(menu); + } + } + + if (this.control && typeof this.control.reset === 'function') + menu.add('Reset camera', function() { + this.control.reset(); + }); + } + + this.FillAttContextMenu(menu); + + return true; + } + + JSROOT.THistPainter.prototype.ButtonClick = function(funcname) { + if (!this.is_main_painter()) return false; + switch(funcname) { + case "ToggleZoom": + if ((this.zoom_xmin !== this.zoom_xmax) || (this.zoom_ymin !== this.zoom_ymax) || (this.zoom_zmin !== this.zoom_zmax)) { + this.Unzoom(); + return true; + } + if (this.draw_content && ('AutoZoom' in this) && (this.Dimension() < 3)) { + this.AutoZoom(); + return true; + } + break; + case "ToggleLogX": this.ToggleLog("x"); break; + case "ToggleLogY": this.ToggleLog("y"); break; + case "ToggleLogZ": this.ToggleLog("z"); break; + case "ToggleStatBox": this.ToggleStat(); return true; break; + } + return false; + } + + JSROOT.THistPainter.prototype.FillToolbar = function() { + var pp = this.pad_painter(true); + if (pp===null) return; + + pp.AddButton(JSROOT.ToolbarIcons.auto_zoom, 'Toggle between unzoom and autozoom-in', 'ToggleZoom'); + pp.AddButton(JSROOT.ToolbarIcons.arrow_right, "Toggle log x", "ToggleLogX"); + pp.AddButton(JSROOT.ToolbarIcons.arrow_up, "Toggle log y", "ToggleLogY"); + if (this.Dimension() > 1) + pp.AddButton(JSROOT.ToolbarIcons.arrow_diag, "Toggle log z", "ToggleLogZ"); + if (this.draw_content) + pp.AddButton(JSROOT.ToolbarIcons.statbox, 'Toggle stat box', "ToggleStatBox"); + } + + + // ======= TH1 painter================================================ + + JSROOT.TH1Painter = function(histo) { + JSROOT.THistPainter.call(this, histo); + } + + JSROOT.TH1Painter.prototype = Object.create(JSROOT.THistPainter.prototype); + + JSROOT.TH1Painter.prototype.ScanContent = function() { + // from here we analyze object content + // therefore code will be moved + + this.nbinsx = this.histo.fXaxis.fNbins; + this.nbinsy = 0; + + this.CreateAxisFuncs(false); + + var hmin = 0, hmin_nz = 0, hmax = 0, hsum = 0, first = true, + left = this.GetSelectIndex("x","left"), + right = this.GetSelectIndex("x","right"), + profile = this.IsTProfile(), value, err; + + for (var i = 0; i < this.nbinsx; ++i) { + value = this.histo.getBinContent(i + 1); + hsum += profile ? this.histo.fBinEntries[i + 1] : value; + + if ((i=right)) continue; + + if (value > 0) + if ((hmin_nz == 0) || (value 0) ? this.histo.getBinError(i + 1) : 0; + + hmin = Math.min(hmin, value - err); + hmax = Math.max(hmax, value + err); + } + + // account overflow/underflow bins + if (profile) + hsum += this.histo.fBinEntries[0] + this.histo.fBinEntries[this.nbinsx + 1]; + else + hsum += this.histo.getBinContent(0) + this.histo.getBinContent(this.nbinsx + 1); + + this.stat_entries = hsum; + if (this.histo.fEntries>1) this.stat_entries = this.histo.fEntries; + + this.hmin = hmin; + this.hmax = hmax; + + this.ymin_nz = hmin_nz; // value can be used to show optimal log scale + + if ((this.nbinsx == 0) || ((Math.abs(hmin) < 1e-300 && Math.abs(hmax) < 1e-300))) { + this.draw_content = false; + hmin = this.ymin; + hmax = this.ymax; + } else { + this.draw_content = true; + } + + if (hmin >= hmax) { + if (hmin == 0) { this.ymin = 0; this.ymax = 1; } else + if (hmin < 0) { this.ymin = 2 * hmin; this.ymax = 0; } + else { this.ymin = 0; this.ymax = hmin * 2; } + } else { + var dy = (hmax - hmin) * 0.05; + this.ymin = hmin - dy; + if ((this.ymin < 0) && (hmin >= 0)) this.ymin = 0; + this.ymax = hmax + dy; + } + + hmin = hmax = null; + var set_zoom = false; + if (this.histo.fMinimum != -1111) { + hmin = this.histo.fMinimum; + if (hmin < this.ymin) + this.ymin = hmin; + else + set_zoom = true; + } + if (this.histo.fMaximum != -1111) { + hmax = this.histo.fMaximum; + if (hmax > this.ymax) + this.ymax = hmax; + else + set_zoom = true; + } + + if (set_zoom) { + this.zoom_ymin = (hmin == null) ? this.ymin : hmin; + this.zoom_ymax = (hmax == null) ? this.ymax : hmax; + } + + // If no any draw options specified, do not try draw histogram + if (!this.options.Bar && !this.options.Hist && + !this.options.Error && !this.options.Same && !this.options.Lego) { + this.draw_content = false; + } + if (this.options.Axis > 0) { // Paint histogram axis only + this.draw_content = false; + } + } + + JSROOT.TH1Painter.prototype.CountStat = function(cond) { + var profile = this.IsTProfile(); + + var stat_sumw = 0, stat_sumwx = 0, stat_sumwx2 = 0, stat_sumwy = 0, stat_sumwy2 = 0; + + var left = this.GetSelectIndex("x", "left"); + var right = this.GetSelectIndex("x", "right"); + + var xx = 0, w = 0, xmax = null, wmax = null; + + for (var i = left; i < right; ++i) { + xx = this.GetBinX(i+0.5); + + if ((cond!=null) && !cond(xx)) continue; + + if (profile) { + w = this.histo.fBinEntries[i + 1]; + stat_sumwy += this.histo.fArray[i + 1]; + stat_sumwy2 += this.histo.fSumw2[i + 1]; + } else { + w = this.histo.getBinContent(i + 1); + } + + if ((xmax==null) || (w>wmax)) { xmax = xx; wmax = w; } + + stat_sumw += w; + stat_sumwx += w * xx; + stat_sumwx2 += w * xx * xx; + } + + // when no range selection done, use original statistic from histogram + if (!this.IsAxisZoomed("x") && (this.histo.fTsumw>0)) { + stat_sumw = this.histo.fTsumw; + stat_sumwx = this.histo.fTsumwx; + stat_sumwx2 = this.histo.fTsumwx2; + } + + var res = { meanx: 0, meany: 0, rmsx: 0, rmsy: 0, integral: stat_sumw, entries: this.stat_entries, xmax:0, wmax:0 }; + + if (stat_sumw > 0) { + res.meanx = stat_sumwx / stat_sumw; + res.meany = stat_sumwy / stat_sumw; + res.rmsx = Math.sqrt(stat_sumwx2 / stat_sumw - res.meanx * res.meanx); + res.rmsy = Math.sqrt(stat_sumwy2 / stat_sumw - res.meany * res.meany); + } + + if (xmax!=null) { + res.xmax = xmax; + res.wmax = wmax; + } + + return res; + } + + JSROOT.TH1Painter.prototype.FillStatistic = function(stat, dostat, dofit) { + if (!this.histo) return false; + + var pave = stat.GetObject(), + data = this.CountStat(), + print_name = dostat % 10, + print_entries = Math.floor(dostat / 10) % 10, + print_mean = Math.floor(dostat / 100) % 10, + print_rms = Math.floor(dostat / 1000) % 10, + print_under = Math.floor(dostat / 10000) % 10, + print_over = Math.floor(dostat / 100000) % 10, + print_integral = Math.floor(dostat / 1000000) % 10, + print_skew = Math.floor(dostat / 10000000) % 10, + print_kurt = Math.floor(dostat / 100000000) % 10; + + if (print_name > 0) + pave.AddText(this.histo.fName); + + if (this.IsTProfile()) { + + if (print_entries > 0) + pave.AddText("Entries = " + stat.Format(data.entries,"entries")); + + if (print_mean > 0) { + pave.AddText("Mean = " + stat.Format(data.meanx)); + pave.AddText("Mean y = " + stat.Format(data.meany)); + } + + if (print_rms > 0) { + pave.AddText("Std Dev = " + stat.Format(data.rmsx)); + pave.AddText("Std Dev y = " + stat.Format(data.rmsy)); + } + + } else { + + if (print_entries > 0) + pave.AddText("Entries = " + stat.Format(data.entries,"entries")); + + if (print_mean > 0) { + pave.AddText("Mean = " + stat.Format(data.meanx)); + } + + if (print_rms > 0) { + pave.AddText("Std Dev = " + stat.Format(data.rmsx)); + } + + if (print_under > 0) { + var res = (this.histo.fArray.length > 0) ? this.histo.fArray[0] : 0; + pave.AddText("Underflow = " + stat.Format(res)); + } + + if (print_over > 0) { + var res = (this.histo.fArray.length > 0) ? this.histo.fArray[this.histo.fArray.length - 1] : 0; + pave.AddText("Overflow = " + stat.Format(res)); + } + + if (print_integral > 0) { + pave.AddText("Integral = " + stat.Format(data.integral,"entries")); + } + + if (print_skew > 0) + pave.AddText("Skew = "); + + if (print_kurt > 0) + pave.AddText("Kurt = "); + } + + if (dofit!=0) { + var f1 = this.FindFunction('TF1'); + if (f1!=null) { + var print_fval = dofit%10; + var print_ferrors = Math.floor(dofit/10) % 10; + var print_fchi2 = Math.floor(dofit/100) % 10; + var print_fprob = Math.floor(dofit/1000) % 10; + + if (print_fchi2 > 0) + pave.AddText("#chi^2 / ndf = " + stat.Format(f1.fChisquare,"fit") + " / " + f1.fNDF); + if (print_fprob > 0) + pave.AddText("Prob = " + (('Math' in JSROOT) ? stat.Format(JSROOT.Math.Prob(f1.fChisquare, f1.fNDF)) : "")); + if (print_fval > 0) { + for(var n=0;n 0) && (parerr.length > 0)) + pave.AddText(parname + " = " + parvalue + " #pm " + parerr); + else + pave.AddText(parname + " = " + parvalue); + } + } + } + } + + // adjust the size of the stats box with the number of lines + var nlines = pave.fLines.arr.length, + stath = nlines * JSROOT.gStyle.StatFontSize; + if ((stath <= 0) || (JSROOT.gStyle.StatFont % 10 === 3)) { + stath = 0.25 * nlines * JSROOT.gStyle.StatH; + pave.fY1NDC = 0.93 - stath; + pave.fY2NDC = 0.93; + } + + return true; + } + + JSROOT.TH1Painter.prototype.DrawBars = function() { + var width = this.frame_width(), height = this.frame_height(); + + this.RecreateDrawG(false, "main_layer"); + + var left = this.GetSelectIndex("x", "left", -1), + right = this.GetSelectIndex("x", "right", 1), + pmain = this.main_painter(), + pad = this.root_pad(), + pthis = this, + i, x1, x2, grx1, grx2, y, gry, w; + + var bars = "", barsl = "", barsr = "", side = this.options.Bar % 10; + + if (side>4) side = 4; + + for (i = left; i < right; ++i) { + x1 = this.GetBinX(i); + x2 = this.GetBinX(i+1); + + if (pmain.logx && (x2 <= 0)) continue; + + grx1 = Math.round(pmain.grx(x1)); + grx2 = Math.round(pmain.grx(x2)); + + y = this.histo.getBinContent(i+1); + if (pmain.logy && (y < pmain.scale_ymin)) continue; + gry = Math.round(pmain.gry(y)); + + w = grx2 - grx1; + grx1 += Math.round(this.histo.fBarOffset/1000*w); + w = Math.round(this.histo.fBarWidth/1000*w); + + if (pmain.swap_xy) + bars += "M0,"+ grx1 + "h" + gry + "v" + w + "h" + (-gry)+ "z"; + else + bars += "M"+grx1+"," + gry + "h" + w + "v" + (height - gry) + "h" + (-w)+ "z"; + + if (side > 0) { + grx2 = grx1 + w; + w = Math.round(w * side / 10); + if (pmain.swap_xy) { + barsl += "M0,"+ grx1 + "h" + gry + "v" + w + "h" + (-gry)+ "z"; + barsr += "M0,"+ grx2 + "h" + gry + "v" + (-w) + "h" + (-gry)+ "z"; + } else { + barsl += "M"+grx1+","+gry + "h" + w + "v" + (height - gry) + "h" + (-w)+ "z"; + barsr += "M"+grx2+","+gry + "h" + (-w) + "v" + (height - gry) + "h" + w + "z"; + } + } + } + + if (bars.length > 0) + this.draw_g.append("svg:path") + .attr("d", bars) + .call(this.fillatt.func); + + if (barsl.length > 0) + this.draw_g.append("svg:path") + .attr("d", barsl) + .call(this.fillatt.func) + .style("fill", d3.rgb(this.fillatt.color).brighter(0.5).toString()); + + if (barsr.length > 0) + this.draw_g.append("svg:path") + .attr("d", barsr) + .call(this.fillatt.func) + .style("fill", d3.rgb(this.fillatt.color).darker(0.5).toString()); + } + + JSROOT.TH1Painter.prototype.DrawBins = function() { + // new method, create svg:path expression ourself directly from histogram + // all points will be used, compress expression when too large + + this.CheckHistDrawAttributes(); + + if (this.options.Bar > 0) + return this.DrawBars(); + + var width = this.frame_width(), height = this.frame_height(); + + if (!this.draw_content || (width<=0) || (height<=0)) + return this.RemoveDrawG(); + + this.RecreateDrawG(false, "main_layer"); + + var left = this.GetSelectIndex("x", "left", -1), + right = this.GetSelectIndex("x", "right", 2), + pmain = this.main_painter(), + pad = this.root_pad(), + pthis = this, + res = "", lastbin = false, + startx, currx, curry, x, grx, y, gry, curry_min, curry_max, prevy, prevx, i, besti, + exclude_zero = (this.options.Error!==10) && (this.options.Mark!==10), + show_errors = (this.options.Error > 0), + show_markers = (this.options.Mark > 0), + path_fill = null, path_err = null, path_marker = null, + endx = "", endy = "", dend = 0, my, yerr1, yerr2, bincont, binerr, mx1, mx2, mpath = ""; + + if (show_errors && !show_markers && (this.histo.fMarkerStyle > 1)) + show_markers = true; + + if (this.options.Error == 12) { + if (this.fillatt.color=='none') show_markers = true; + else path_fill = ""; + } else + if (this.options.Error > 0) path_err = ""; + + if (show_markers) { + // draw markers also when e2 option was specified + if (!this.markeratt) + this.markeratt = JSROOT.Painter.createAttMarker(this.histo); + if (this.markeratt.size > 0) { + // simply use relative move from point, can optimize in the future + path_marker = ""; + this.markeratt.reset_pos(); + } else { + show_markers = false; + } + } + + // if there are too many points, exclude many vertical drawings at the same X position + // instead define min and max value and made min-max drawing + var use_minmax = ((right-left) > 3*width); + + if (this.options.Error == 11) { + var lw = this.lineatt.width + JSROOT.gStyle.EndErrorSize; + endx = "m0," + lw + "v-" + 2*lw + "m0," + lw; + endy = "m" + lw + ",0h-" + 2*lw + "m" + lw + ",0"; + dend = Math.floor((this.lineatt.width-1)/2); + } + + var draw_markers = show_errors || show_markers; + + if (draw_markers) use_minmax = true; + + for (i = left; i <= right; ++i) { + + x = this.GetBinX(i); + + if (this.logx && (x <= 0)) continue; + + grx = Math.round(pmain.grx(x)); + + lastbin = (i === right); + + if (lastbin && (left= -yerr1) && (my <= height + yerr2)) { + if (path_fill !== null) + path_fill +="M" + mx1 +","+(my-yerr1) + + "h" + (mx2-mx1) + "v" + (yerr1+yerr2+1) + "h-" + (mx2-mx1) + "z"; + if (path_err !== null) + path_err +="M" + (mx1+dend) +","+ my + endx + "h" + (mx2-mx1-2*dend) + endx + + "M" + Math.round((mx1+mx2)/2) +"," + (my-yerr1+dend) + endy + "v" + (yerr1+yerr2-2*dend) + endy; + if (path_marker !== null) + path_marker += this.markeratt.create((mx1+mx2)/2, my); + } + } + } + + // when several points as same X differs, need complete logic + if (!draw_markers && ((curry_min !== curry_max) || (prevy !== curry_min))) { + + if (prevx !== currx) + res += "h"+(currx-prevx); + + if (curry === curry_min) { + if (curry_max !== prevy) + res += "v" + (curry_max - prevy); + if (curry_min !== curry_max) + res += "v" + (curry_min - curry_max); + } else { + if (curry_min !== prevy) + res += "v" + (curry_min - prevy); + if (curry_max !== curry_min) + res += "v" + (curry_max - curry_min); + if (curry !== curry_max) + res += "v" + (curry - curry_max); + } + + prevx = currx; + prevy = curry; + } + + if (lastbin && (prevx !== grx)) + res += "h"+(grx-prevx); + + besti = i; + curry_min = curry_max = curry = gry; + currx = grx; + } + } else + if ((gry !== curry) || lastbin) { + if (grx !== currx) res += "h"+(grx-currx); + if (gry !== curry) res += "v"+(gry-curry); + curry = gry; + currx = grx; + } + } + + if ((this.fillatt.color !== 'none') && (res.length>0)) { + var h0 = (height+3); + if ((this.hmin>=0) && (pmain.gry(0) < height)) h0 = Math.round(pmain.gry(0)); + res += "L"+currx+","+h0 + "L"+startx+","+h0 + "Z"; + } + + if (draw_markers) { + + if ((path_fill !== null) && (path_fill.length > 0)) + this.draw_g.append("svg:path") + .attr("d", path_fill) + .call(this.fillatt.func); + + if ((path_err !== null) && (path_err.length > 0)) + this.draw_g.append("svg:path") + .attr("d", path_err) + .call(this.lineatt.func) + + if ((path_marker !== null) && (path_marker.length > 0)) + this.draw_g.append("svg:path") + .attr("d", path_marker) + .call(this.markeratt.func); + + } else + if (res.length > 0) { + this.draw_g.append("svg:path") + .attr("d", res) + .style("stroke-linejoin","miter") + .call(this.lineatt.func) + .call(this.fillatt.func); + } + } + + JSROOT.TH1Painter.prototype.GetBinTips = function(bin) { + var tips = [], name = this.GetTipName(), pmain = this.main_painter(); + if (name.length>0) tips.push(name); + + var x1 = this.GetBinX(bin), + x2 = this.GetBinX(bin+1), + cont = this.histo.getBinContent(bin+1); + + if ((this.options.Error > 0) || (this.options.Mark > 0)) { + tips.push("x = " + pmain.AxisAsText("x", (x1+x2)/2)); + tips.push("y = " + pmain.AxisAsText("y", cont)); + if (this.options.Error > 0) { + tips.push("error x = " + ((x2 - x1) / 2).toPrecision(4)); + tips.push("error y = " + this.histo.getBinError(bin + 1).toPrecision(4)); + } + } else { + tips.push("bin = " + (bin+1)); + + if (pmain.x_kind === 'labels') + tips.push("x = " + pmain.AxisAsText("x", x1)); + else + if (pmain.x_kind === 'time') + tips.push("x = " + pmain.AxisAsText("x", (x1+x2)/2)); + else + tips.push("x = [" + pmain.AxisAsText("x", x1) + ", " + pmain.AxisAsText("x", x2) + ")"); + + if (cont === Math.round(cont)) + tips.push("entries = " + cont); + else + tips.push("entries = " + JSROOT.FFormat(cont, JSROOT.gStyle.StatFormat)); + } + + return tips; + } + + JSROOT.TH1Painter.prototype.ProcessTooltip = function(pnt) { + if ((pnt === null) || !this.draw_content || (this.options.Lego > 0)) { + if (this.draw_g !== null) + this.draw_g.select(".tooltip_bin").remove(); + this.ProvideUserTooltip(null); + return null; + } + + var width = this.frame_width(), + height = this.frame_height(), + pmain = this.main_painter(), + pad = this.root_pad(), + painter = this, + findbin = null, show_rect = true, + grx1, midx, grx2, gry1, midy, gry2, + left = this.GetSelectIndex("x", "left", -1), + right = this.GetSelectIndex("x", "right", 2), + l = left, r = right; + + function GetBinGrX(i) { + var x1 = painter.GetBinX(i); + if ((x1<0) && pmain.logx) return null; + return pmain.grx(x1); + } + + function GetBinGrY(i) { + var y = painter.histo.getBinContent(i + 1); + if (pmain.logy && (y < painter.scale_ymin)) + return pmain.swap_xy ? -1000 : 10*height; + return Math.round(pmain.gry(y)); + } + + while (l < r-1) { + var m = Math.round((l+r)*0.5); + + var xx = GetBinGrX(m); + if (xx === null) { l = m; continue; } + + if (xx < pnt.x - 0.5) l = m; else + if (xx > pnt.x + 0.5) r = m; else { l++; r--; } + } + + findbin = r = l; + grx1 = GetBinGrX(findbin); + + while ((l>left) && (GetBinGrX(l-1) > grx1 - 1.0)) --l; + while ((r height/10) + findbin = Math.round(l + (r-l) / height * pnt.y); + + grx1 = GetBinGrX(findbin); + } + + grx1 = Math.round(grx1); + grx2 = Math.round(GetBinGrX(findbin+1)); + + if (this.options.Bar > 0) { + var w = grx2 - grx1; + grx1 += Math.round(this.histo.fBarOffset/1000*w); + grx2 = grx1 + Math.round(this.histo.fBarWidth/1000*w); + } + + midx = Math.round((grx1+grx2)/2); + + midy = gry1 = gry2 = GetBinGrY(findbin); + + if ((this.options.Error > 0) || (this.options.Mark > 0)) { + + show_rect = true; + + var msize = 3; + if (this.markeratt) msize = Math.max(msize, 2+Math.round(this.markeratt.size * 4)); + + // show at least 6 pixels as tooltip rect + if (grx2 - grx1 < 2*msize) { grx1 = midx-msize; grx2 = midx+msize; } + + if (this.options.Error > 0) { + var cont = this.histo.getBinContent(findbin+1); + var binerr = this.histo.getBinError(findbin+1); + + gry1 = Math.round(pmain.gry(cont + binerr)); // up + gry2 = Math.round(pmain.gry(cont - binerr)); // down + + if ((cont==0) && this.IsTProfile()) findbin = null; + } + + gry1 = Math.min(gry1, midy - msize); + gry2 = Math.max(gry2, midy + msize); + + if (!pnt.touch && (pnt.nproc === 1)) + if ((pnt.ygry2)) findbin = null; + + } else { + + // if histogram alone, use old-style with rects + // if there are too many points at pixel, use circle + show_rect = (pnt.nproc === 1) && (right-left < width); + + if (show_rect) { + // for mouse events mouse pointer should be under the curve + if ((pnt.y < gry1) && !pnt.touch) findbin = null; + + gry2 = height; + + if ((this.fillatt.color !== 'none') && (this.hmin>=0)) { + gry2 = Math.round(pmain.gry(0)); + if ((gry2 > height) || (gry2 <= gry1)) gry2 = height; + } + } + } + + if (findbin!==null) { + // if bin on boundary found, check that x position is ok + if ((findbin === left) && (grx1 > pnt.x + 2)) findbin = null; else + if ((findbin === right-1) && (grx2 < pnt.x - 2)) findbin = null; else + // if bars option used check that bar is not match + if ((pnt.x < grx1 - 2) || (pnt.x > grx2 + 2)) findbin = null; + } + + + var ttrect = this.draw_g.select(".tooltip_bin"); + + if ((findbin === null) || ((gry2 <= 0) || (gry1 >= height))) { + ttrect.remove(); + this.ProvideUserTooltip(null); + return null; + } + + var res = { x: midx, y: midy, + color1: this.lineatt.color, color2: this.fillatt.color, + lines: this.GetBinTips(findbin) }; + + if (show_rect) { + + if (ttrect.empty()) + ttrect = this.draw_g.append("svg:rect") + .attr("class","tooltip_bin h1bin") + .style("pointer-events","none"); + + res.changed = ttrect.property("current_bin") !== findbin; + + if (res.changed) + ttrect.attr("x", grx1) + .attr("width", grx2-grx1) + .attr("y", gry1) + .attr("height", gry2-gry1) + .style("opacity", "0.3") + .property("current_bin", findbin); + + res.exact = (Math.abs(midy - pnt.y) <= 5) || ((pnt.y>=gry1) && (pnt.y<=gry2)); + + res.menu = true; // one could show context menu + // distance to middle point, use to decide which menu to activate + res.menu_dist = Math.sqrt((midx-pnt.x)*(midx-pnt.x) + (midy-pnt.y)*(midy-pnt.y)); + + } else { + var radius = this.lineatt.width + 3; + + if (ttrect.empty()) + ttrect = this.draw_g.append("svg:circle") + .attr("class","tooltip_bin") + .style("pointer-events","none") + .attr("r", radius) + .call(this.lineatt.func) + .call(this.fillatt.func); + + res.exact = (Math.abs(midx - pnt.x) <= radius) && (Math.abs(midy - pnt.y) <= radius); + + res.menu = res.exact; // show menu only when mouse pointer exactly over the histogram + res.menu_dist = Math.sqrt((midx-pnt.x)*(midx-pnt.x) + (midy-pnt.y)*(midy-pnt.y)); + + res.changed = ttrect.property("current_bin") !== findbin; + + if (res.changed) + ttrect.attr("cx", midx) + .attr("cy", midy) + .property("current_bin", findbin); + } + + if (this.IsUserTooltipCallback() && res.changed) { + this.ProvideUserTooltip({ obj: this.histo, name: this.histo.fName, + bin: findbin, cont: this.histo.getBinContent(findbin+1), + grx: midx, gry: midy }); + } + + return res; + } + + + JSROOT.TH1Painter.prototype.FillHistContextMenu = function(menu) { + + menu.add("Auto zoom-in", this.AutoZoom); + + menu.addDrawMenu("Draw with", ["hist", "p", "e", "e1", "pe2", "lego"], function(arg) { + this.options = this.DecodeOptions(arg); + + // redraw all objects + this.RedrawPad(); + + // if (this.options.Lego == 0) this.AddInteractive(); + }); + } + + JSROOT.TH1Painter.prototype.AutoZoom = function() { + var left = this.GetSelectIndex("x", "left", -1), + right = this.GetSelectIndex("x", "right", 1), + dist = right - left; + + if (dist == 0) return; + + // first find minimum + var min = this.histo.getBinContent(left + 1); + for (var indx = left; indx < right; ++indx) + if (this.histo.getBinContent(indx + 1) < min) + min = this.histo.getBinContent(indx + 1); + if (min>0) return; // if all points positive, no chance for autoscale + + while ((left < right) && (this.histo.getBinContent(left + 1) <= min)) ++left; + while ((left < right) && (this.histo.getBinContent(right) <= min)) --right; + + if ((right - left < dist) && (left < right)) + this.Zoom(this.GetBinX(left), this.GetBinX(right)); + } + + JSROOT.TH1Painter.prototype.CanZoomIn = function(axis,min,max) { + if ((axis=="x") && (this.GetIndexX(max,0.5) - this.GetIndexX(min,0) > 1)) return true; + + if ((axis=="y") && (Math.abs(max-min) > Math.abs(this.ymax-this.ymin)*1e-6)) return true; + + // check if it makes sense to zoom inside specified axis range + return false; + } + + JSROOT.TH1Painter.prototype.Draw2D = function(call_back) { + if (typeof this.Create3DScene === 'function') + this.Create3DScene(-1); + if (typeof this.DrawColorPalette === 'function') + this.DrawColorPalette(false); + + this.DrawAxes(); + this.DrawGrids(); + this.DrawBins(); + this.DrawTitle(); + this.AddInteractive(); + JSROOT.CallBack(call_back); + } + + JSROOT.TH1Painter.prototype.Draw3D = function(call_back) { + JSROOT.AssertPrerequisites('more2d;3d', function() { + this.Create3DScene = JSROOT.Painter.HPainter_Create3DScene; + this.Draw3D = JSROOT.Painter.TH1Painter_Draw3D; + this.Draw3D(call_back); + }.bind(this)); + } + + JSROOT.THistPainter.prototype.Get3DToolTip = function(indx) { + var tip = { bin: indx }, arr; + switch (this.Dimension()) { + case 1: + tip.ix = indx; tip.iy = 1; + tip.value = this.histo.getBinContent(tip.ix); + arr = this.GetBinTips(indx-1); + break; + case 2: { + tip.ix = indx % (this.nbinsx + 2); + tip.iy = (indx - tip.ix) / (this.nbinsx + 2); + tip.value = this.histo.getBinContent(tip.ix, tip.iy); + arr = this.GetBinTips(tip.ix-1, tip.iy-1); + break; + } + case 3: { + tip.ix = indx % (this.nbinsx+2); + tip.iy = ((indx - tip.ix) / (this.nbinsx+2)) % (this.nbinsy+2); + tip.iz = (indx - tip.ix - tip.iy * (this.nbinsx+2)) / (this.nbinsx+2) / (this.nbinsy+2); + tip.value = this.GetObject().getBinContent(tip.ix, tip.iy, tip.iz); + arr = this.GetBinTips(tip.ix-1, tip.iy-1, tip.iz-1); + break; + } + } + + if (arr) { + tip.info = arr[0]; + for (var n=1;n 0) ? "Draw3D" : "Draw2D"; + + this[func_name](null, resize); + } + + JSROOT.Painter.drawHistogram1D = function(divid, histo, opt) { + // create painter and add it to canvas + var painter = new JSROOT.TH1Painter(histo); + + painter.SetDivId(divid, 1); + + // here we deciding how histogram will look like and how will be shown + painter.options = painter.DecodeOptions(opt); + + painter.CheckPadRange(); + + painter.ScanContent(); + + painter.CreateXY(); + + if (JSROOT.gStyle.AutoStat && painter.create_canvas) + painter.CreateStat(); + + var func_name = (painter.options.Lego > 0) ? "Draw3D" : "Draw2D"; + + painter[func_name](function() { + painter.DrawNextFunction(0, function() { + + if (painter.options.Lego === 0) { + // painter.AddInteractive(); + if (painter.options.AutoZoom) painter.AutoZoom(); + } + + painter.FillToolbar(); + painter.DrawingReady(); + }); + }); + + return painter; + } + + // ===================================================================================== + + JSROOT.Painter.drawText = function(divid, text) { + var painter = new JSROOT.TObjectPainter(text); + painter.SetDivId(divid, 2); + + painter.Redraw = function() { + var text = this.GetObject(), + w = this.pad_width(), h = this.pad_height(), + pos_x = text.fX, pos_y = text.fY, + tcolor = JSROOT.Painter.root_colors[text.fTextColor], + use_pad = true, latex_kind = 0, fact = 1.; + + if (text.TestBit(JSROOT.BIT(14))) { + // NDC coordiantes + pos_x = pos_x * w; + pos_y = (1 - pos_y) * h; + } else + if (this.main_painter() !== null) { + w = this.frame_width(); h = this.frame_height(); use_pad = false; + pos_x = this.main_painter().grx(pos_x); + pos_y = this.main_painter().gry(pos_y); + } else + if (this.root_pad() !== null) { + pos_x = this.ConvertToNDC("x", pos_x) * w; + pos_y = (1 - this.ConvertToNDC("y", pos_y)) * h; + } else { + text.fTextAlign = 22; + pos_x = w/2; + pos_y = h/2; + if (text.fTextSize === 0) text.fTextSize = 0.05; + if (text.fTextColor === 0) text.fTextColor = 1; + } + + this.RecreateDrawG(use_pad, use_pad ? "text_layer" : "upper_layer"); + + if (text._typename == 'TLatex') { latex_kind = 1; fact = 0.9; } else + if (text._typename == 'TMathText') { latex_kind = 2; fact = 0.8; } + + this.StartTextDrawing(text.fTextFont, Math.round(text.fTextSize*Math.min(w,h)*fact)); + + this.DrawText(text.fTextAlign, Math.round(pos_x), Math.round(pos_y), 0, 0, text.fTitle, tcolor, latex_kind); + + this.FinishTextDrawing(); + } + + painter.Redraw(); + return painter.DrawingReady(); + } + + // ================= painter of raw text ======================================== + + JSROOT.RawTextPainter = function(txt) { + JSROOT.TBasePainter.call(this); + this.txt = txt; + return this; + } + + JSROOT.RawTextPainter.prototype = Object.create( JSROOT.TBasePainter.prototype ); + + JSROOT.RawTextPainter.prototype.RedrawObject = function(obj) { + this.txt = obj; + this.Draw(); + return true; + } + + JSROOT.RawTextPainter.prototype.Draw = function() { + var txt = this.txt.value; + if (txt==null) txt = ""; + + var mathjax = 'mathjax' in this.txt; + + if (!mathjax && !('as_is' in this.txt)) { + var arr = txt.split("\n"); txt = ""; + for (var i = 0; i < arr.length; ++i) + txt += "
    " + arr[i] + "
    "; + } + + var frame = this.select_main(); + var main = frame.select("div"); + if (main.empty()) + main = frame.append("div") + .style('max-width','100%') + .style('max-height','100%') + .style('overflow','auto'); + + main.html(txt); + + // (re) set painter to first child element + this.SetDivId(this.divid); + + if (mathjax) { + if (this['loading_mathjax']) return; + this['loading_mathjax'] = true; + var painter = this; + JSROOT.AssertPrerequisites('mathjax', function() { + painter['loading_mathjax'] = false; + if (typeof MathJax == 'object') { + MathJax.Hub.Queue(["Typeset", MathJax.Hub, frame.node()]); + } + }); + } + } + + JSROOT.Painter.drawRawText = function(divid, txt, opt) { + var painter = new JSROOT.RawTextPainter(txt); + painter.SetDivId(divid); + painter.Draw(); + return painter.DrawingReady(); + } + + // ===================== hierarchy scanning functions ================================== + + JSROOT.Painter.FolderHierarchy = function(item, obj) { + + if ((obj==null) || !('fFolders' in obj) || (obj.fFolders==null)) return false; + + if (obj.fFolders.arr.length===0) { item._more = false; return true; } + + item._childs = []; + + for ( var i = 0; i < obj.fFolders.arr.length; ++i) { + var chld = obj.fFolders.arr[i]; + item._childs.push( { + _name : chld.fName, + _kind : "ROOT." + chld._typename, + _obj : chld + }); + } + return true; + } + + JSROOT.Painter.TaskHierarchy = function(item, obj) { + // function can be used for different derived classes + // we show not only child tasks, but all complex data members + + if ((obj==null) || !('fTasks' in obj) || (obj.fTasks==null)) return false; + + JSROOT.Painter.ObjectHierarchy(item, obj, { exclude: ['fTasks', 'fName'] } ); + + if ((obj.fTasks.arr.length===0) && (item._childs.length==0)) { item._more = false; return true; } + + // item._childs = []; + + for ( var i = 0; i < obj.fTasks.arr.length; ++i) { + var chld = obj.fTasks.arr[i]; + item._childs.push( { + _name : chld.fName, + _kind : "ROOT." + chld._typename, + _obj : chld + }); + } + return true; + } + + + JSROOT.Painter.ListHierarchy = function(folder, lst) { + if (lst._typename != 'TList' && lst._typename != 'TObjArray' && lst._typename != 'TClonesArray') return false; + + if ((lst.arr === undefined) || (lst.arr.length === 0)) { + folder._more = false; + return true; + } + + folder._childs = []; + for ( var i = 0; i < lst.arr.length; ++i) { + var obj = lst.arr[i]; + + var item; + + if (obj===null) { + item = { + _name: i.toString(), + _kind: "ROOT.NULL", + _title: "NULL", + _obj: null + } + } else { + item = { + _name : obj.fName, + _kind : "ROOT." + obj._typename, + _title : obj.fTitle, + _obj : obj + }; + // if name is integer value, it should match array index + if ((item._name === undefined) || + (!isNaN(parseInt(item._name)) && (parseInt(item._name)!==i)) + || (lst.arr.indexOf(obj) 0 ? "ROOT.TBranch" : "ROOT.TLeafF" + } + + node._childs.push(subitem); + + if (nb_leaves > 0) { + subitem._childs = []; + for (var j = 0; j < nb_leaves; ++j) { + var leafitem = { + _name : branch.fLeaves.arr[j].fName, + _kind : "ROOT.TLeafF" + } + subitem._childs.push(leafitem); + } + } + } + + return true; + } + + JSROOT.Painter.KeysHierarchy = function(folder, keys, file, dirname) { + + if (keys === undefined) return false; + + folder._childs = []; + + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + + var item = { + _name : key.fName + ";" + key.fCycle, + _cycle : key.fCycle, + _kind : "ROOT." + key.fClassName, + _title : key.fTitle, + _keyname : key.fName, + _readobj : null, + _parent : folder + }; + + if ('fRealName' in key) + item._realname = key.fRealName + ";" + key.fCycle; + + if (key.fClassName == 'TDirectory' || key.fClassName == 'TDirectoryFile') { + var dir = null; + if ((dirname!=null) && (file!=null)) dir = file.GetDir(dirname + key.fName); + if (dir == null) { + item._more = true; + item._expand = function(node, obj) { + // one can get expand call from child objects - ignore them + return JSROOT.Painter.KeysHierarchy(node, obj.fKeys); + } + } else { + // remove cycle number - we have already directory + item._name = key.fName; + JSROOT.Painter.KeysHierarchy(item, dir.fKeys, file, dirname + key.fName + "/"); + } + } else + if ((key.fClassName == 'TList') && (key.fName == 'StreamerInfo')) { + item._name = 'StreamerInfo'; + item._kind = "ROOT.TStreamerInfoList"; + item._title = "List of streamer infos for binary I/O"; + item._readobj = file.fStreamerInfos; + } + + folder._childs.push(item); + } + + return true; + } + + JSROOT.Painter.ObjectHierarchy = function(top, obj, args) { + if ((top==null) || (obj==null)) return false; + + // check nosimple property in all parents + var nosimple = true, prnt = top; + while (prnt) { + if ('_nosimple' in prnt) { nosimple = prnt._nosimple; break; } + prnt = prnt._parent; + } + + top._childs = []; + if (!('_obj' in top)) + top._obj = obj; + else + if (top._obj !== obj) alert('object missmatch'); + + if (!('_title' in top) && ('_typename' in obj)) + top._title = "ROOT." + obj._typename; + + for (var key in obj) { + if (key == '_typename') continue; + var fld = obj[key]; + if (typeof fld == 'function') continue; + if (args && args.exclude && (args.exclude.indexOf(key)>=0)) continue; + + var item = { + _parent : top, + _name : key + }; + + if (fld === null) { + item._value = item._title = "null"; + if (!nosimple) top._childs.push(item); + continue; + } + + var proto = Object.prototype.toString.apply(fld); + var simple = false; + + if ((proto.lastIndexOf('Array]') == proto.length-6) && (proto.indexOf('[object')==0)) { + item._title = item._kind + " len=" + fld.length; + simple = (proto != '[object Array]'); + if (fld.length === 0) { + item._value = "[ ]"; + item._more = false; // hpainter will not try to expand again + } else { + item._value = "[...]"; + item._more = true; + item._expand = JSROOT.Painter.ObjectHierarchy; + item._obj = fld; + } + } else + if (typeof fld == 'object') { + if ('_typename' in fld) + item._kind = item._title = "ROOT." + fld._typename; + + // check if object already shown in hierarchy (circular dependency) + var curr = top, inparent = false; + while (curr && !inparent) { + inparent = (curr._obj === fld); + curr = curr._parent; + } + + if (inparent) { + item._value = "{ prnt }"; + simple = true; + } else { + item._obj = fld; + item._value = "{ }"; + if (fld._typename == 'TColor') item._value = JSROOT.Painter.MakeColorRGB(fld); + } + } else + if ((typeof fld == 'number') || (typeof fld == 'boolean')) { + simple = true; + if (key == 'fBits') + item._value = "0x" + fld.toString(16); + else + item._value = fld.toString(); + item._vclass = 'h_value_num'; + } else + if (typeof fld == 'string') { + simple = true; + item._value = '"' + fld + '"'; + item._vclass = 'h_value_str'; + } else { + simple = true; + alert('miss ' + key + ' ' + typeof fld); + } + + if (!simple || !nosimple) + top._childs.push(item); + } + return true; + } + + // =========== painter of hierarchical structures ================================= + + JSROOT.hpainter = null; // global pointer + + JSROOT.HierarchyPainter = function(name, frameid, backgr) { + JSROOT.TBasePainter.call(this); + this.name = name; + this.h = null; // hierarchy + this.with_icons = true; + this.background = backgr; + this.files_monitoring = (frameid == null); // by default files monitored when nobrowser option specified + this.nobrowser = frameid === null; + if (!this.nobrowser) this.SetDivId(frameid); + + // remember only very first instance + if (JSROOT.hpainter == null) + JSROOT.hpainter = this; + } + + JSROOT.HierarchyPainter.prototype = Object.create(JSROOT.TBasePainter.prototype); + + JSROOT.HierarchyPainter.prototype.ToggleFloatBrowser = function(force_mode) { + if (!this.nobrowser || !this.disp) return; + + var elem = d3.select("#"+this.disp.frameid); + if (elem.empty()) return; + + var container = d3.select(elem.node().parentNode); + + var main = container.select('.float_browser'); + + if (main.empty()) { + if (force_mode === false) return; + var div = container.append("div").attr("class","jsroot"); + main = div.append("div").attr("class","float_browser").style('left', '-320px'); + main.transition().delay(700).style('left', '5px'); + this.SetDivId(main.node()); + this.RefreshHtml(); + } else { + if (main.style('left') == '5px') { + if (force_mode !== true) + main.transition().delay(700).style('left', '-320px'); + } else { + if (force_mode !== false) + main.transition().delay(700).style('left', '5px'); + } + } + } + + JSROOT.HierarchyPainter.prototype.Cleanup = function() { + // clear drawing and browser + this.clear(true); + } + + JSROOT.HierarchyPainter.prototype.FileHierarchy = function(file) { + var painter = this; + + var folder = { + _name : file.fFileName, + _kind : "ROOT.TFile", + _file : file, + _fullurl : file.fFullURL, + _had_direct_read : false, + // this is central get method, item or itemname can be used + _get : function(item, itemname, callback) { + + var fff = this; // file item + + if (item && item._readobj) + return JSROOT.CallBack(callback, item, item._readobj); + + if (item!=null) itemname = painter.itemFullName(item, fff); + + function ReadFileObject(file) { + if (fff._file==null) fff._file = file; + + if (file == null) return JSROOT.CallBack(callback, item, null); + + file.ReadObject(itemname, function(obj) { + + // if object was read even when item didnot exist try to reconstruct new hierarchy + if ((item==null) && (obj!=null)) { + // first try to found last read directory + var d = painter.Find({name:itemname, top:fff, last_exists:true, check_keys:true }); + if ((d!=null) && ('last' in d) && (d.last!=fff)) { + // reconstruct only subdir hierarchy + var dir = file.GetDir(painter.itemFullName(d.last, fff)); + if (dir) { + d.last._name = d.last._keyname; + var dirname = painter.itemFullName(d.last, fff); + JSROOT.Painter.KeysHierarchy(d.last, dir.fKeys, file, dirname + "/"); + } + } else { + // reconstruct full file hierarchy + JSROOT.Painter.KeysHierarchy(fff, file.fKeys, file, ""); + } + item = painter.Find({name:itemname, top: fff}); + } + + if (item!=null) { + item._readobj = obj; + // remove cycle number for objects supporting expand + if ('_expand' in item) item._name = item._keyname; + } + + JSROOT.CallBack(callback, item, obj); + }); + } + + if (fff._file != null) { + ReadFileObject(fff._file); + } else { + // try to reopen ROOT file + new JSROOT.TFile(fff._fullurl, ReadFileObject); + } + } + }; + + JSROOT.Painter.KeysHierarchy(folder, file.fKeys, file, ""); + + return folder; + } + + JSROOT.HierarchyPainter.prototype.ForEach = function(callback, top) { + + if (top==null) top = this.h; + if ((top==null) || (typeof callback != 'function')) return; + function each_item(item) { + callback(item); + if ('_childs' in item) + for (var n = 0; n < item._childs.length; ++n) { + item._childs[n]._parent = item; + each_item(item._childs[n]); + } + } + + each_item(top); + } + + JSROOT.HierarchyPainter.prototype.Find = function(arg) { + // search item in the hierarchy + // One could specify simply item name or object with following arguments + // name: item to search + // force: specified elements will be created when not exists + // last_exists: when specified last parent element will be returned + // check_keys: check TFile keys with cycle suffix + // top: element to start search from + + function find_in_hierarchy(top, fullname) { + + if (!fullname || (fullname.length == 0) || (top==null)) return top; + + var pos = -1; + + function process_child(child) { + // set parent pointer when searching child + child._parent = top; + if ((pos + 1 == fullname.length) || (pos < 0)) return child; + + return find_in_hierarchy(child, fullname.substr(pos + 1)); + } + + do { + // we try to find element with slashes inside + pos = fullname.indexOf("/", pos + 1); + + var localname = (pos < 0) ? fullname : fullname.substr(0, pos); + + if (top._childs) { + // first try to find direct matched item + for (var i = 0; i < top._childs.length; ++i) + if (top._childs[i]._name == localname) + return process_child(top._childs[i]); + + // if allowed, try to found item with key + if (arg.check_keys) + for (var i = 0; i < top._childs.length; ++i) { + if ((typeof top._childs[i]._keyname === 'string') && + (top._childs[i]._keyname === localname)) + return process_child(top._childs[i]); + } + + var allow_index = arg.allow_index; + if ((localname[0] === '[') && (localname[localname.length-1] === ']') && + !isNaN(parseInt(localname.substr(1,localname.length-2)))) { + allow_index = true; + localname = localname.substr(1,localname.length-2); + } + + // when search for the elements it could be allowed to check index + if (allow_index) { + var indx = parseInt(localname); + if (!isNaN(indx) && (indx>=0) && (indx 0); + + return (arg.last_exists && top) ? { last: top, rest: fullname } : null; + } + + var top = this.h; + var itemname = ""; + + if (typeof arg == 'string') { itemname = arg; arg = {}; } else + if (typeof arg == 'object') { itemname = arg.name; if ('top' in arg) top = arg.top; } else + return null; + + return find_in_hierarchy(top, itemname); + } + + JSROOT.HierarchyPainter.prototype.itemFullName = function(node, uptoparent) { + var res = ""; + + while (node && ('_parent' in node)) { + if (res.length > 0) res = "/" + res; + res = node._name + res; + node = node._parent; + if (uptoparent && (node === uptoparent)) break; + } + + return res; + } + + JSROOT.HierarchyPainter.prototype.ExecuteCommand = function(itemname, callback) { + // execute item marked as 'Command' + // If command requires additional arguments, they could be specified as extra arguments + // Or they will be requested interactive + + var hitem = this.Find(itemname); + var url = itemname + "/cmd.json"; + var pthis = this; + var d3node = d3.select((typeof callback == 'function') ? null : callback); + + if ('_numargs' in hitem) + for (var n = 0; n < hitem._numargs; ++n) { + var argname = "arg" + (n+1); + var argvalue = null; + if (n+20) newparentname+="/"; + hpainter.get( { arg: newparentname + d.rest, rest: d.rest }, call_back, options); + }); + } + + if ((item !== null) && (typeof item._obj == 'object')) + return JSROOT.CallBack(call_back, item, item._obj); + + // normally search _get method in the parent items + var curr = item; + while (curr != null) { + if (('_get' in curr) && (typeof curr._get == 'function')) + return curr._get(item, null, call_back, options); + curr = ('_parent' in curr) ? curr._parent : null; + } + + JSROOT.CallBack(call_back, item, null); + } + + JSROOT.HierarchyPainter.prototype.draw = function(divid, obj, drawopt) { + // just envelope, one should be able to redefine it for sub-classes + return JSROOT.draw(divid, obj, drawopt); + } + + JSROOT.HierarchyPainter.prototype.redraw = function(divid, obj, drawopt) { + // just envelope, one should be able to redefine it for sub-classes + return JSROOT.redraw(divid, obj, drawopt); + } + + JSROOT.HierarchyPainter.prototype.player = function(itemname, option, call_back) { + var item = this.Find(itemname); + + if (!item || !('_player' in item)) return JSROOT.CallBack(call_back, null); + + var hpainter = this; + + var prereq = ('_prereq' in item) ? item['_prereq'] : ''; + + JSROOT.AssertPrerequisites(prereq, function() { + + var player_func = JSROOT.findFunction(item._player); + if (player_func == null) return JSROOT.CallBack(call_back, null); + + hpainter.CreateDisplay(function(mdi) { + var res = null; + if (mdi) res = player_func(hpainter, itemname, option); + JSROOT.CallBack(call_back, res); + }); + }); + } + + JSROOT.HierarchyPainter.prototype.canDisplay = function(item, drawopt) { + if (item == null) return false; + if ('_player' in item) return true; + if (drawopt == 'inspect') return true; + var handle = JSROOT.getDrawHandle(item._kind, drawopt); + return (handle!=null) && ('func' in handle); + } + + JSROOT.HierarchyPainter.prototype.isItemDisplayed = function(itemname) { + var mdi = this.GetDisplay(); + if (!mdi) return false; + + return mdi.FindFrame(itemname) !== null; + + } + + JSROOT.HierarchyPainter.prototype.display = function(itemname, drawopt, call_back) { + var h = this, + painter = null, + updating = false, + frame_name = itemname, + marker = "::_display_on_frame_::", + p = drawopt ? drawopt.indexOf(marker) : -1; + + if (p>=0) { + frame_name = drawopt.substr(p + marker.length); + drawopt = drawopt.substr(0, p); + } + + function display_callback() { + if (painter) painter.SetItemName(itemname, updating ? null : drawopt); // mark painter as created from hierarchy + JSROOT.CallBack(call_back, painter, itemname); + } + + h.CreateDisplay(function(mdi) { + + if (!mdi) return display_callback(); + + var item = h.Find(itemname); + + if ((item!=null) && ('_player' in item)) + return h.player(itemname, drawopt, display_callback); + + updating = (typeof(drawopt)=='string') && (drawopt.indexOf("update:")==0); + + if (updating) { + drawopt = drawopt.substr(7); + if ((item==null) || ('_doing_update' in item)) return display_callback(); + item._doing_update = true; + } + + if (item!=null) { + if (!h.canDisplay(item, drawopt)) return display_callback(); + } + + var divid = ""; + if ((typeof(drawopt)=='string') && (drawopt.indexOf("divid:")>=0)) { + var pos = drawopt.indexOf("divid:"); + divid = drawopt.slice(pos+6); + drawopt = drawopt.slice(0, pos); + } + + JSROOT.progress("Loading " + itemname); + + h.get(itemname, function(item, obj) { + + JSROOT.progress(); + + if (updating && item) delete item['_doing_update']; + if (obj==null) return display_callback(); + + JSROOT.progress("Drawing " + itemname); + + if (divid.length > 0) { + painter = updating ? h.redraw(divid, obj, drawopt) : h.draw(divid, obj, drawopt); + } else { + mdi.ForEachPainter(function(p, frame) { + if (p.GetItemName() != itemname) return; + // verify that object was drawn with same option as specified now (if any) + if (!updating && (drawopt!=null) && (p.GetItemDrawOpt()!=drawopt)) return; + painter = p; + mdi.ActivateFrame(frame); + painter.RedrawObject(obj); + }); + } + + if (painter==null) { + if (updating) { + JSROOT.console("something went wrong - did not found painter when doing update of " + itemname); + } else { + var frame = mdi.FindFrame(frame_name, true); + d3.select(frame).html(""); + mdi.ActivateFrame(frame); + painter = h.draw(d3.select(frame).attr("id"), obj, drawopt); + item._painter = painter; + if (JSROOT.gStyle.DragAndDrop) + h.enable_dropping(frame, itemname); + } + } + + JSROOT.progress(); + + if (painter === null) return display_callback(); + + painter.WhenReady(display_callback); + + }, drawopt); + }); + } + + JSROOT.HierarchyPainter.prototype.enable_dragging = function(element, itemname) { + // here is not defined - implemented with jquery + } + + JSROOT.HierarchyPainter.prototype.enable_dropping = function(frame, itemname) { + // here is not defined - implemented with jquery + } + + JSROOT.HierarchyPainter.prototype.dropitem = function(itemname, divid, call_back) { + var h = this; + + h.get(itemname, function(item, obj) { + if (obj!=null) { + var painter = h.draw(divid, obj, "same"); + if (painter) painter.WhenReady(function() { painter.SetItemName(itemname); }); + } + + JSROOT.CallBack(call_back); + }); + + return true; + } + + JSROOT.HierarchyPainter.prototype.updateItems = function(items) { + // argument is item name or array of string with items name + // only already drawn items will be update with same draw option + + if ((this.disp == null) || (items==null)) return; + + var draw_items = [], draw_options = []; + + this.disp.ForEachPainter(function(p) { + var itemname = p.GetItemName(); + if ((itemname==null) || (draw_items.indexOf(itemname)>=0)) return; + if (typeof items == 'array') { + if (items.indexOf(itemname) < 0) return; + } else { + if (items != itemname) return; + } + draw_items.push(itemname); + draw_options.push("update:" + p.GetItemDrawOpt()); + }, true); // only visible panels are considered + + if (draw_items.length > 0) + this.displayAll(draw_items, draw_options); + } + + + JSROOT.HierarchyPainter.prototype.updateAll = function(only_auto_items, only_items) { + // method can be used to fetch new objects and update all existing drawings + // if only_auto_items specified, only automatic items will be updated + + if (this.disp == null) return; + + var allitems = [], options = [], hpainter = this; + + // first collect items + this.disp.ForEachPainter(function(p) { + var itemname = p.GetItemName(); + var drawopt = p.GetItemDrawOpt(); + if ((itemname==null) || (allitems.indexOf(itemname)>=0)) return; + + var item = hpainter.Find(itemname); + if ((item==null) || ('_not_monitor' in item) || ('_player' in item)) return; + var forced = false; + + if ('_always_monitor' in item) { + forced = true; + } else { + var handle = JSROOT.getDrawHandle(item._kind); + if (handle && ('monitor' in handle)) { + if ((handle.monitor===false) || (handle.monitor=='never')) return; + if (handle.monitor==='always') forced = true; + } + } + + if (forced || !only_auto_items) { + allitems.push(itemname); + options.push("update:" + drawopt); + } + }, true); // only visible panels are considered + + var painter = this; + + // force all files to read again (normally in non-browser mode) + if (this.files_monitoring && !only_auto_items) + this.ForEachRootFile(function(item) { + painter.ForEach(function(fitem) { delete fitem._readobj; }, item); + delete item._file; + }); + + if (allitems.length > 0) + this.displayAll(allitems, options); + } + + JSROOT.HierarchyPainter.prototype.displayAll = function(items, options, call_back) { + + if ((items == null) || (items.length == 0)) return JSROOT.CallBack(call_back); + + var h = this; + + if (!options) options = []; + while (options.length < items.length) + options.push(""); + + if ((options.length == 1) && (options[0] == "iotest")) { + h.clear(); + d3.select("#" + h.disp_frameid).html("

    Start I/O test "+ ('IO' in JSROOT ? "Mode=" + JSROOT.IO.Mode : "") + "

    ") + + var tm0 = new Date(); + return h.get(items[0], function(item, obj) { + var tm1 = new Date(); + d3.select("#" + h.disp_frameid).append("h2").html("Item " + items[0] + " reading time = " + (tm1.getTime() - tm0.getTime()) + "ms"); + return JSROOT.CallBack(call_back); + }); + } + + var dropitems = new Array(items.length); + + // First of all check that items are exists, look for cycle extension and plus sign + for (var i = 0; i < items.length; ++i) { + dropitems[i] = null; + + var item = items[i], can_split = true; + + if ((item.length>1) && (item[0]=='\'') && (item[item.length-1]=='\'')) { + items[i] = item.substr(1, item.length-2); + can_split = false; + } + + var elem = h.Find({ name: items[i], check_keys: true }); + if (elem) { items[i] = h.itemFullName(elem); continue; } + + if (can_split && (items[i].indexOf("+") > 0)) { + dropitems[i] = items[i].split("+"); + items[i] = dropitems[i].shift(); + // allow to specify _same_ item in different file + for (var j = 0; j < dropitems[i].length; ++j) { + var pos = dropitems[i][j].indexOf("_same_"); + if ((pos>0) && (h.Find(dropitems[i][j])==null)) + dropitems[i][j] = dropitems[i][j].substr(0,pos) + items[i].substr(pos); + } + } + + // also check if subsequent items has _same_, than use name from first item + var pos = items[i].indexOf("_same_"); + if ((pos>0) && !h.Find(items[i]) && (i>0)) + items[i] = items[i].substr(0,pos) + items[0].substr(pos); + } + + // now check that items can be displayed + for (var n = items.length-1; n>=0; --n) { + var hitem = h.Find(items[n]); + if ((hitem==null) || h.canDisplay(hitem, options[n])) continue; + // try to expand specified item + h.expand(items[n]); + items.splice(n, 1); + options.splice(n, 1); + dropitems.splice(n, 1); + } + + if (items.length == 0) return JSROOT.CallBack(call_back); + + var frame_names = []; + for (var n=0; n=0) + fname = items[n] + "_" + k++; + frame_names.push(fname); + } + + h.CreateDisplay(function(mdi) { + if (!mdi) return JSROOT.CallBack(call_back); + + // Than create empty frames for each item + for (var i = 0; i < items.length; ++i) + if (options[i].indexOf('update:')!==0) { + mdi.CreateFrame(frame_names[i]); + options[i] += "::_display_on_frame_::"+frame_names[i]; + } + + // We start display of all items parallel + for (var i = 0; i < items.length; ++i) + h.display(items[i], options[i], DisplayCallback.bind(this,i)); + + function DisplayCallback(indx, painter, itemname) { + items[indx] = null; // mark item as ready + DropNextItem(indx, painter); + } + + function DropNextItem(indx, painter) { + if (painter && dropitems[indx] && (dropitems[indx].length>0)) + return h.dropitem(dropitems[indx].shift(), painter.divid, DropNextItem.bind(this, indx, painter)); + + var isany = false; + for (var cnt = 0; cnt < items.length; ++cnt) + if (items[cnt]!==null) isany = true; + + // only when items drawn and all sub-items dropped, one could perform call-back + if (!isany) JSROOT.CallBack(call_back); + } + + }); + } + + JSROOT.HierarchyPainter.prototype.reload = function() { + var hpainter = this; + if ('_online' in this.h) + this.OpenOnline(this.h._online, function() { + hpainter.RefreshHtml(); + }); + } + + JSROOT.HierarchyPainter.prototype.UpdateTreeNode = function() { + // dummy function, will be redefined when jquery part loaded + } + + JSROOT.HierarchyPainter.prototype.actiavte = function(items, force) { + // activate (select) specified item + // if force specified, all required sub-levels will be opened + + if (typeof items == 'string') items = [ items ]; + + var active = [], // array of elements to activate + painter = this, // painter itself + update = []; // array of elements to update + this.ForEach(function(item) { if (item._background) { active.push(item); delete item._background; } }); + + function mark_active() { + if (typeof painter.UpdateBackground !== 'function') return; + + for (var n=update.length-1;n>=0;--n) + painter.UpdateTreeNode(update[n]); + + for (var n=0;n0) newname+="/"; + find_next(newname + d.rest, d.now_found); + }); + } + hitem = d.last; + } + + if (hitem) { + // check that item is visible (opened), otherwise should enable parent + + var prnt = hitem._parent; + while (prnt) { + if (!prnt._isopen) { + if (force) { + prnt._isopen = true; + if (update.indexOf(prnt)<0) update.push(prnt); + } else { + hitem = prnt; break; + } + } + prnt = prnt._parent; + } + + + hitem._background = 'grey'; + if (active.indexOf(hitem)<0) active.push(hitem); + } + + find_next(); + } + + // use recursion + find_next(); + } + + JSROOT.HierarchyPainter.prototype.expand = function(itemname, call_back, d3cont) { + var hpainter = this, hitem = this.Find(itemname); + + if (!hitem && d3cont) return JSROOT.CallBack(call_back); + + function DoExpandItem(_item, _obj, _name) { + if (!_name) _name = hpainter.itemFullName(_item); + + // try to use expand function + if (_obj && _item && (typeof _item._expand === 'function')) { + if (_item._expand(_item, _obj)) { + _item._isopen = true; + if (_item._parent && !_item._parent._isopen) { + _item._parent._isopen = true; // also show parent + hpainter.UpdateTreeNode(_item._parent); + } else { + hpainter.UpdateTreeNode(_item, d3cont); + } + JSROOT.CallBack(call_back, _item); + return true; + } + } + + if (!('_expand' in _item)) { + var handle = JSROOT.getDrawHandle(_item._kind, "::expand"); + if (handle && ('expand' in handle)) { + JSROOT.AssertPrerequisites(handle.prereq, function() { + _item._expand = JSROOT.findFunction(handle.expand); + if (!_item._expand) + delete _item._expand; + else + hpainter.expand(_name, call_back, d3cont); + }); + return true; + } + } + + if (_obj && JSROOT.Painter.ObjectHierarchy(_item, _obj)) { + _item._isopen = true; + if (_item._parent && !_item._parent._isopen) { + _item._parent._isopen = true; // also show parent + hpainter.UpdateTreeNode(_item._parent); + } else { + hpainter.UpdateTreeNode(_item, d3cont); + } + JSROOT.CallBack(call_back, _item); + return true; + } + + return false; + } + + if (hitem) { + // item marked as it cannot be expanded + if (('_more' in hitem) && !hitem._more) return JSROOT.CallBack(call_back); + + if (DoExpandItem(hitem, hitem._obj, itemname)) return; + } + + JSROOT.progress("Loading " + itemname); + + this.get(itemname, function(item, obj) { + + JSROOT.progress(); + + if (obj && DoExpandItem(item, obj)) return; + + JSROOT.CallBack(call_back); + }, "hierarchy_expand" ); // indicate that we getting element for expand, can handle it differently + + } + + JSROOT.HierarchyPainter.prototype.GetTopOnlineItem = function(item) { + if (item!=null) { + while ((item!=null) && (!('_online' in item))) item = item._parent; + return item; + } + + if (this.h==null) return null; + if ('_online' in this.h) return this.h; + if ((this.h._childs!=null) && ('_online' in this.h._childs[0])) return this.h._childs[0]; + return null; + } + + + JSROOT.HierarchyPainter.prototype.ForEachJsonFile = function(call_back) { + if (this.h==null) return; + if ('_jsonfile' in this.h) + return JSROOT.CallBack(call_back, this.h); + + if (this.h._childs!=null) + for (var n = 0; n < this.h._childs.length; ++n) { + var item = this.h._childs[n]; + if ('_jsonfile' in item) JSROOT.CallBack(call_back, item); + } + } + + JSROOT.HierarchyPainter.prototype.OpenJsonFile = function(filepath, call_back) { + var isfileopened = false; + this.ForEachJsonFile(function(item) { if (item._jsonfile==filepath) isfileopened = true; }); + if (isfileopened) return JSROOT.CallBack(call_back); + + var pthis = this; + JSROOT.NewHttpRequest(filepath,'object', function(res) { + if (res == null) return JSROOT.CallBack(call_back); + var h1 = { _jsonfile: filepath, _kind: "ROOT." + res._typename, _jsontmp: res, _name: filepath.split("/").pop() }; + if ('fTitle' in res) h1._title = res.fTitle; + h1._get = function(item,itemname,callback) { + if ('_jsontmp' in item) { + //var res = item._jsontmp; + //delete item._jsontmp; + return JSROOT.CallBack(callback, item, item._jsontmp); + } + JSROOT.NewHttpRequest(item._jsonfile, 'object', function(res) { + item._jsontmp = res; + return JSROOT.CallBack(callback, item, item._jsontmp); + }).send(null); + } + if (pthis.h == null) pthis.h = h1; else + if (pthis.h._kind == 'TopFolder') pthis.h._childs.push(h1); else { + var h0 = pthis.h; + var topname = ('_jsonfile' in h0) ? "Files" : "Items"; + pthis.h = { _name: topname, _kind: 'TopFolder', _childs : [h0, h1] }; + } + + pthis.RefreshHtml(call_back); + }).send(null); + } + + JSROOT.HierarchyPainter.prototype.ForEachRootFile = function(call_back) { + if (this.h==null) return; + if ((this.h._kind == "ROOT.TFile") && (this.h._file!=null)) + return JSROOT.CallBack(call_back, this.h); + + if (this.h._childs != null) + for (var n = 0; n < this.h._childs.length; ++n) { + var item = this.h._childs[n]; + if ((item._kind == 'ROOT.TFile') && ('_fullurl' in item)) + JSROOT.CallBack(call_back, item); + } + } + + JSROOT.HierarchyPainter.prototype.OpenRootFile = function(filepath, call_back) { + // first check that file with such URL already opened + + var isfileopened = false; + this.ForEachRootFile(function(item) { if (item._fullurl==filepath) isfileopened = true; }); + if (isfileopened) return JSROOT.CallBack(call_back); + + var pthis = this; + + JSROOT.OpenFile(filepath, function(file) { + if (file == null) return JSROOT.CallBack(call_back); + var h1 = pthis.FileHierarchy(file); + h1._isopen = true; + if (pthis.h == null) pthis.h = h1; else + if (pthis.h._kind == 'TopFolder') pthis.h._childs.push(h1); else { + var h0 = pthis.h; + var topname = (h0._kind == "ROOT.TFile") ? "Files" : "Items"; + pthis.h = { _name: topname, _kind: 'TopFolder', _childs : [h0, h1] }; + } + + pthis.RefreshHtml(call_back); + }); + } + + JSROOT.HierarchyPainter.prototype.GetFileProp = function(itemname) { + var item = this.Find(itemname); + if (item == null) return null; + + var subname = item._name; + while (item._parent) { + item = item._parent; + if ('_file' in item) + return { kind: "file", fileurl: item._file.fURL, itemname: subname }; + + if ('_jsonfile' in item) + return { kind: "json", fileurl: item._jsonfile, itemname: subname }; + + subname = item._name + "/" + subname; + } + + return null; + } + + JSROOT.MarkAsStreamerInfo = function(h,item,obj) { + // this function used on THttpServer to mark streamer infos list + // as fictional TStreamerInfoList class, which has special draw function + if ((obj!=null) && (obj._typename=='TList')) + obj._typename = 'TStreamerInfoList'; + } + + JSROOT.HierarchyPainter.prototype.GetOnlineItemUrl = function(item) { + // returns URL, which could be used to request item from the online server + if ((item!=null) && (typeof item == "string")) item = this.Find(item); + var top = this.GetTopOnlineItem(item); + if (item==null) return null; + + var urlpath = this.itemFullName(item, top); + if (top && ('_online' in top) && (top._online!="")) urlpath = top._online + urlpath; + return urlpath; + } + + JSROOT.HierarchyPainter.prototype.GetOnlineItem = function(item, itemname, callback, option) { + // method used to request object from the http server + + var url = itemname, h_get = false, req = "", req_kind = "object", pthis = this, draw_handle = null; + + if (option === 'hierarchy_expand') { h_get = true; option = undefined; } + + if (item != null) { + url = this.GetOnlineItemUrl(item); + var func = null; + if ('_kind' in item) draw_handle = JSROOT.getDrawHandle(item._kind); + + if (h_get) { + req = 'h.json?compact=3'; + item._expand = JSROOT.Painter.OnlineHierarchy; // use proper expand function + } else + if ('_make_request' in item) { + func = JSROOT.findFunction(item._make_request); + } else + if ((draw_handle!=null) && ('make_request' in draw_handle)) { + func = draw_handle.make_request; + } + + if (typeof func == 'function') { + // ask to make request + var dreq = func(pthis, item, url, option); + // result can be simple string or object with req and kind fields + if (dreq!=null) + if (typeof dreq == 'string') req = dreq; else { + if ('req' in dreq) req = dreq.req; + if ('kind' in dreq) req_kind = dreq.kind; + } + } + + if ((req.length==0) && (item._kind.indexOf("ROOT.")!=0)) + req = 'item.json.gz?compact=3'; + } + + if ((itemname==null) && (item!=null) && ('_cached_draw_object' in this) && (req.length == 0)) { + // special handling for drawGUI when cashed + var obj = this._cached_draw_object; + delete this._cached_draw_object; + return JSROOT.CallBack(callback, item, obj); + } + + if (req.length == 0) req = 'root.json.gz?compact=3'; + + if (url.length > 0) url += "/"; + url += req; + + var itemreq = JSROOT.NewHttpRequest(url, req_kind, function(obj) { + + var func = null; + + if (!h_get && (item!=null) && ('_after_request' in item)) { + func = JSROOT.findFunction(item._after_request); + } else + if ((draw_handle!=null) && ('after_request' in draw_handle)) + func = draw_handle.after_request; + + if (typeof func == 'function') { + var res = func(pthis, item, obj, option, itemreq); + if ((res!=null) && (typeof res == "object")) obj = res; + } + + JSROOT.CallBack(callback, item, obj); + }); + + itemreq.send(null); + } + + JSROOT.Painter.OnlineHierarchy = function(node, obj) { + // central function for expand of all online items + + if ((obj != null) && (node != null) && ('_childs' in obj)) { + + for (var n=0;n3) && + ((arr[n].lastIndexOf(".js")==arr[n].length-3) || + (arr[n].lastIndexOf(".css")==arr[n].length-4))) { + if (scripts.indexOf(arr[n])<0) scripts+=arr[n]+";"; + } else { + if (modules.indexOf(arr[n])<0) modules+=arr[n]+";"; + } + } + }); + + if (scripts.length > 0) scripts = "user:" + scripts; + + // use AssertPrerequisites, while it protect us from race conditions + JSROOT.AssertPrerequisites(modules + scripts, function() { + + painter.ForEach(function(item) { + if (!('_drawfunc' in item) || !('_kind' in item)) return; + var typename = "kind:" + item._kind; + if (item._kind.indexOf('ROOT.')==0) typename = item._kind.slice(5); + var drawopt = item._drawopt; + if (!JSROOT.canDraw(typename) || (drawopt!=null)) + JSROOT.addDrawFunc({ name: typename, func: item._drawfunc, script: item._drawscript, opt: drawopt }); + }); + + JSROOT.CallBack(user_callback, painter); + }); + } + + if (!server_address) server_address = ""; + + if (typeof server_address == 'object') { + var h = server_address; + server_address = ""; + return AdoptHierarchy(h); + } + + JSROOT.NewHttpRequest(server_address + "h.json?compact=3", 'object', AdoptHierarchy).send(null); + } + + JSROOT.HierarchyPainter.prototype.GetOnlineProp = function(itemname) { + var item = this.Find(itemname); + if (item == null) return null; + + var subname = item._name; + while (item._parent != null) { + item = item._parent; + + if ('_online' in item) { + return { + server : item._online, + itemname : subname + }; + } + subname = item._name + "/" + subname; + } + + return null; + } + + JSROOT.HierarchyPainter.prototype.FillOnlineMenu = function(menu, onlineprop, itemname) { + + var painter = this; + + var node = this.Find(itemname); + var opts = JSROOT.getDrawOptions(node._kind, 'nosame'); + var handle = JSROOT.getDrawHandle(node._kind); + var root_type = ('_kind' in node) ? node._kind.indexOf("ROOT.") == 0 : false; + + if (opts != null) + menu.addDrawMenu("Draw", opts, function(arg) { painter.display(itemname, arg); }); + + if ((node['_childs'] == null) && (node['_more'] || root_type)) + menu.add("Expand", function() { painter.expand(itemname); }); + + if (handle && ('execute' in handle)) + menu.add("Execute", function() { painter.ExecuteCommand(itemname, menu.tree_node); }); + + var drawurl = onlineprop.server + onlineprop.itemname + "/draw.htm"; + var separ = "?"; + if (this.IsMonitoring()) { + drawurl += separ + "monitoring=" + this.MonitoringInterval(); + separ = "&"; + } + + if (opts != null) + menu.addDrawMenu("Draw in new window", opts, function(arg) { window.open(drawurl+separ+"opt=" +arg); }); + + if ((opts!=null) && (opts.length > 0) && root_type) + menu.addDrawMenu("Draw as png", opts, function(arg) { + window.open(onlineprop.server + onlineprop.itemname + "/root.png?w=400&h=300&opt=" + arg); + }); + + if ('_player' in node) + menu.add("Player", function() { painter.player(itemname); }); + } + + JSROOT.HierarchyPainter.prototype.Adopt = function(h) { + this.h = h; + this.RefreshHtml(); + } + + JSROOT.HierarchyPainter.prototype.SetMonitoring = function(val) { + this._monitoring_on = false; + this._monitoring_interval = 3000; + + val = (val === undefined) ? 0 : parseInt(val); + + if (!isNaN(val) && (val>0)) { + this._monitoring_on = true; + this._monitoring_interval = Math.max(100,val); + } + } + + JSROOT.HierarchyPainter.prototype.MonitoringInterval = function(val) { + // returns interval + return ('_monitoring_interval' in this) ? this._monitoring_interval : 3000; + } + + JSROOT.HierarchyPainter.prototype.EnableMonitoring = function(on) { + this._monitoring_on = on; + } + + JSROOT.HierarchyPainter.prototype.IsMonitoring = function() { + return this._monitoring_on; + } + + JSROOT.HierarchyPainter.prototype.SetDisplay = function(layout, frameid) { + if ((frameid==null) && (typeof layout == 'object')) { + this.disp = layout; + this.disp_kind = 'custom'; + this.disp_frameid = null; + } else { + this.disp_kind = layout; + this.disp_frameid = frameid; + } + } + + JSROOT.HierarchyPainter.prototype.GetLayout = function() { + return this.disp_kind; + } + + JSROOT.HierarchyPainter.prototype.clear = function(withbrowser) { + if (this.disp) { + this.disp.Reset(); + delete this.disp; + } + + this.ForEach(function(item) { + delete item._painter; // remove reference on the painter + // when only display cleared, try to clear all browser items + if (!withbrowser && (typeof item.clear=='function')) item.clear(); + }); + + if (withbrowser) { + this.select_main().html(""); + delete this.h; + } + } + + JSROOT.HierarchyPainter.prototype.GetDisplay = function() { + return ('disp' in this) ? this.disp : null; + } + + JSROOT.HierarchyPainter.prototype.CreateDisplay = function(callback) { + + var h = this; + + if ('disp' in this) { + if ((h.disp.NumDraw() > 0) || (h.disp_kind == "custom")) return JSROOT.CallBack(callback, h.disp); + h.disp.Reset(); + delete h.disp; + } + + // check that we can found frame where drawing should be done + if (document.getElementById(this.disp_frameid) == null) + return JSROOT.CallBack(callback, null); + + if (h.disp_kind == "simple") + h.disp = new JSROOT.SimpleDisplay(h.disp_frameid); + else + if (h.disp_kind.search("grid") == 0) + h.disp = new JSROOT.GridDisplay(h.disp_frameid, h.disp_kind); + else + return JSROOT.AssertPrerequisites('jq2d', function() { h.CreateDisplay(callback); }); + + JSROOT.CallBack(callback, h.disp); + } + + JSROOT.HierarchyPainter.prototype.updateOnOtherFrames = function(painter, obj) { + // function should update object drawings for other painters + var mdi = this.disp; + if (mdi==null) return false; + + var isany = false; + mdi.ForEachPainter(function(p, frame) { + if ((p===painter) || (p.GetItemName() != painter.GetItemName())) return; + mdi.ActivateFrame(frame); + p.RedrawObject(obj); + isany = true; + }); + return isany; + } + + JSROOT.HierarchyPainter.prototype.CheckResize = function(size) { + if ('disp' in this) + this.disp.CheckMDIResize(null, size); + } + + JSROOT.HierarchyPainter.prototype.StartGUI = function(h0, call_back) { + var hpainter = this, + filesarr = JSROOT.GetUrlOptionAsArray("file;files"), + jsonarr = JSROOT.GetUrlOptionAsArray("json"), + filesdir = JSROOT.GetUrlOption("path"), + expanditems = JSROOT.GetUrlOptionAsArray("expand"); + + if (expanditems.length==0 && (JSROOT.GetUrlOption("expand")=="")) expanditems.push(""); + + if (filesdir!=null) { + for (var i=0;i0)) + this.disp_kind = layout; + else + switch (itemsarr.length) { + case 0: + case 1: this.disp_kind = 'simple'; break; + case 2: this.disp_kind = 'grid 1x2'; break; + default: this.disp_kind = 'flex'; + } + } + + if (JSROOT.GetUrlOption('files_monitoring')!=null) this.files_monitoring = true; + + this.SetMonitoring(monitor); + + function OpenAllFiles() { + if (jsonarr.length>0) + hpainter.OpenJsonFile(jsonarr.shift(), OpenAllFiles); + else if (filesarr.length>0) + hpainter.OpenRootFile(filesarr.shift(), OpenAllFiles); + else if (expanditems.length>0) + hpainter.expand(expanditems.shift(), OpenAllFiles); + else + hpainter.displayAll(itemsarr, optionsarr, function() { + hpainter.RefreshHtml(); + + JSROOT.RegisterForResize(hpainter); + + // assign regular update only when monitoring specified (or when work with online application) + if (h0 || hpainter.GetTopOnlineItem() || hpainter.IsMonitoring()) + setInterval(function() { hpainter.updateAll(!hpainter.IsMonitoring()); }, hpainter.MonitoringInterval()); + + JSROOT.CallBack(call_back); + }); + } + + function AfterOnlineOpened() { + // check if server enables monitoring + if (('_monitoring' in hpainter.h) && (monitor==null)) { + hpainter.SetMonitoring(hpainter.h._monitoring); + } + + if (('_layout' in hpainter.h) && (layout==null)) { + hpainter.disp_kind = hpainter.h._layout; + } + + if (('_loadfile' in hpainter.h) && (filesarr.length==0)) { + filesarr = JSROOT.ParseAsArray(hpainter.h._loadfile); + } + + if (('_drawitem' in hpainter.h) && (itemsarr.length==0)) { + itemsarr = JSROOT.ParseAsArray(hpainter.h._drawitem); + optionsarr = JSROOT.ParseAsArray(hpainter.h['_drawopt']); + } + + OpenAllFiles(); + } + + if (h0) hpainter.OpenOnline(h0, AfterOnlineOpened); + else OpenAllFiles(); + } + + JSROOT.BuildNobrowserGUI = function() { + var myDiv = d3.select('#simpleGUI'); + var online = false, drawing = false; + + if (myDiv.empty()) { + online = true; + myDiv = d3.select('#onlineGUI'); + if (myDiv.empty()) { myDiv = d3.select('#drawGUI'); drawing = true; } + if (myDiv.empty()) return alert('no div for simple nobrowser gui found'); + } + + JSROOT.Painter.readStyleFromURL(); + + d3.select('html').style('height','100%'); + d3.select('body').style({ 'min-height':'100%', 'margin':'0px', "overflow": "hidden"}); + + myDiv.style({"position":"absolute", "left":"1px", "top" :"1px", "bottom" :"1px", "right": "1px"}); + + var hpainter = new JSROOT.HierarchyPainter('root', null); + hpainter.SetDisplay(JSROOT.GetUrlOption("layout", null, "simple"), myDiv.attr('id')); + + var h0 = null; + if (online) { + var func = JSROOT.findFunction('GetCachedHierarchy'); + if (typeof func == 'function') h0 = func(); + if (typeof h0 != 'object') h0 = ""; + } + + hpainter.StartGUI(h0, function() { + if (!drawing) return; + var func = JSROOT.findFunction('GetCachedObject'); + var obj = (typeof func == 'function') ? JSROOT.JSONR_unref(func()) : null; + if (obj!=null) hpainter['_cached_draw_object'] = obj; + var opt = JSROOT.GetUrlOption("opt"); + + hpainter.display("", opt, function(obj_painter) { + if (JSROOT.GetUrlOption("websocket")!==null) + obj_painter.OpenWebsocket(); + }); + }); + } + + JSROOT.Painter.drawStreamerInfo = function(divid, lst) { + var painter = new JSROOT.HierarchyPainter('sinfo', divid, 'white'); + + painter.h = { _name : "StreamerInfo", _childs : [] }; + + for ( var i = 0; i < lst.arr.length; ++i) { + var entry = lst.arr[i] + + if (entry._typename == "TList") continue; + + if (typeof (entry.fName) == 'undefined') { + JSROOT.console("strange element in StreamerInfo with type " + entry._typename); + continue; + } + + var item = { + _name : entry.fName + ";" + entry.fClassVersion, + _kind : "class " + entry.fName, + _title : "class:" + entry.fName + ' version:' + entry.fClassVersion + ' checksum:' + entry.fCheckSum, + _icon: "img_class", + _childs : [] + }; + + if (entry.fTitle != '') item._title += ' ' + entry.fTitle; + + painter.h._childs.push(item); + + if (typeof entry.fElements == 'undefined') continue; + for ( var l = 0; l < entry.fElements.arr.length; ++l) { + var elem = entry.fElements.arr[l]; + if ((elem == null) || (typeof (elem.fName) == 'undefined')) continue; + var info = elem.fTypeName + " " + elem.fName + ";"; + if (elem.fTitle != '') info += " // " + elem.fTitle; + item._childs.push({ _name : info, _title: elem.fTypeName, _kind:elem.fTypeName, _icon: (elem.fTypeName == 'BASE') ? "img_class" : "img_member" }); + } + if (item._childs.length == 0) delete item._childs; + } + + painter.select_main().style('overflow','auto'); + + painter.RefreshHtml(function() { + painter.SetDivId(divid); + painter.DrawingReady(); + }); + + return painter; + } + + JSROOT.Painter.drawInspector = function(divid, obj) { + var painter = new JSROOT.HierarchyPainter('inspector', divid, 'white'); + painter.default_by_click = "expand"; // that painter tries to do by default + painter.with_icons = false; + painter.h = { _name: "Object", _title: "ROOT." + obj._typename, _click_action: "expand", _nosimple: false }; + if ((typeof obj.fName === 'string') && (obj.fName.length>0)) + painter.h._name = obj.fName; + + painter.select_main().style('overflow','auto'); + + JSROOT.Painter.ObjectHierarchy(painter.h, obj); + painter.RefreshHtml(function() { + painter.SetDivId(divid); + painter.DrawingReady(); + }); + + return painter; + } + + // ================================================================ + + // JSROOT.MDIDisplay - class to manage multiple document interface for drawings + + JSROOT.MDIDisplay = function(frameid) { + this.frameid = frameid; + d3.select("#"+this.frameid).property('mdi', this); + } + + JSROOT.MDIDisplay.prototype.ForEachFrame = function(userfunc, only_visible) { + // method dedicated to iterate over existing panels + // provided userfunc is called with arguemnts (frame) + + console.warn("ForEachFrame not implemented in MDIDisplay"); + } + + JSROOT.MDIDisplay.prototype.ForEachPainter = function(userfunc, only_visible) { + // method dedicated to iterate over existing panles + // provided userfunc is called with arguemnts (painter, frame) + + this.ForEachFrame(function(frame) { + var dummy = new JSROOT.TObjectPainter(); + dummy.SetDivId(d3.select(frame).attr('id'), -1); + dummy.ForEachPainter(function(painter) { userfunc(painter, frame); }); + }, only_visible); + } + + JSROOT.MDIDisplay.prototype.NumDraw = function() { + var cnt = 0; + this.ForEachFrame(function() { ++cnt; }); + return cnt; + } + + JSROOT.MDIDisplay.prototype.FindFrame = function(searchtitle, force) { + var found_frame = null; + + this.ForEachFrame(function(frame) { + if (d3.select(frame).attr('frame_title') == searchtitle) + found_frame = frame; + }); + + if ((found_frame == null) && force) + found_frame = this.CreateFrame(searchtitle); + + return found_frame; + } + + JSROOT.MDIDisplay.prototype.ActivateFrame = function(frame) { + // do nothing by default + } + + JSROOT.MDIDisplay.prototype.CheckMDIResize = function(only_frame_id, size) { + // perform resize for each frame + var resized_frame = null; + + this.ForEachPainter(function(painter, frame) { + + if ((only_frame_id !== null) && (d3.select(frame).attr('id') != only_frame_id)) return; + + if ((painter.GetItemName()!==null) && (typeof painter.CheckResize == 'function')) { + // do not call resize for many painters on the same frame + if (resized_frame === frame) return; + painter.CheckResize(size); + resized_frame = frame; + } + }); + } + + JSROOT.MDIDisplay.prototype.Reset = function() { + + this.ForEachFrame(function(frame) { + JSROOT.cleanup(frame); + }); + + d3.select("#"+this.frameid).html("").property('mdi', null); + } + + JSROOT.MDIDisplay.prototype.Draw = function(title, obj, drawopt) { + // draw object with specified options + if (!obj) return; + + if (!JSROOT.canDraw(obj._typename, drawopt)) return; + + var frame = this.FindFrame(title, true); + + this.ActivateFrame(frame); + + return JSROOT.redraw(d3.select(frame).attr("id"), obj, drawopt); + } + + + // ================================================== + + JSROOT.CustomDisplay = function() { + JSROOT.MDIDisplay.call(this, "dummy"); + this.frames = {}; // array of configured frames + } + + JSROOT.CustomDisplay.prototype = Object.create(JSROOT.MDIDisplay.prototype); + + JSROOT.CustomDisplay.prototype.AddFrame = function(divid, itemname) { + if (!(divid in this.frames)) this.frames[divid] = ""; + + this.frames[divid] += (itemname + ";"); + } + + JSROOT.CustomDisplay.prototype.ForEachFrame = function(userfunc, only_visible) { + var ks = Object.keys(this.frames); + for (var k = 0; k < ks.length; ++k) { + var node = d3.select("#"+ks[k]); + if (!node.empty()) + JSROOT.CallBack(userfunc, node.node()); + } + } + + JSROOT.CustomDisplay.prototype.CreateFrame = function(title) { + var ks = Object.keys(this.frames); + for (var k = 0; k < ks.length; ++k) { + var items = this.frames[ks[k]]; + if (items.indexOf(title+";")>=0) + return d3.select("#"+ks[k]).node(); + } + return null; + } + + JSROOT.CustomDisplay.prototype.Reset = function() { + JSROOT.MDIDisplay.prototype.Reset.call(this); + this.ForEachFrame(function(frame) { + d3.select(frame).html(""); + }); + } + + // ================================================== + + JSROOT.SimpleDisplay = function(frameid) { + JSROOT.MDIDisplay.call(this, frameid); + } + + JSROOT.SimpleDisplay.prototype = Object.create(JSROOT.MDIDisplay.prototype); + + JSROOT.SimpleDisplay.prototype.ForEachFrame = function(userfunc, only_visible) { + var node = d3.select("#"+this.frameid + "_simple_display"); + if (!node.empty()) + JSROOT.CallBack(userfunc, node.node()); + } + + JSROOT.SimpleDisplay.prototype.CreateFrame = function(title) { + + JSROOT.cleanup(this.frameid+"_simple_display"); + + return d3.select("#"+this.frameid) + .html("") + .append("div") + .attr("id", this.frameid + "_simple_display") + .style("width", "100%") + .style("height", "100%") + .style("overflow" ,"hidden") + .attr("frame_title", title) + .node(); + } + + JSROOT.SimpleDisplay.prototype.Reset = function() { + JSROOT.MDIDisplay.prototype.Reset.call(this); + // try to remove different properties from the div + d3.select("#"+this.frameid).html(""); + } + + // ================================================ + + JSROOT.GridDisplay = function(frameid, sizex, sizey) { + // create grid display object + // one could use followinf arguments + // new JSROOT.GridDisplay('yourframeid','4x4'); + // new JSROOT.GridDisplay('yourframeid','3x2'); + // new JSROOT.GridDisplay('yourframeid', 3, 4); + + JSROOT.MDIDisplay.call(this, frameid); + this.cnt = 0; + if (typeof sizex == "string") { + if (sizex.search("grid") == 0) + sizex = sizex.slice(4).trim(); + + var separ = sizex.search("x"); + + if (separ > 0) { + sizey = parseInt(sizex.slice(separ + 1)); + sizex = parseInt(sizex.slice(0, separ)); + } else { + sizex = parseInt(sizex); + sizey = sizex; + } + + if (isNaN(sizex)) sizex = 3; + if (isNaN(sizey)) sizey = 3; + } + + if (!sizex) sizex = 3; + if (!sizey) sizey = sizex; + this.sizex = sizex; + this.sizey = sizey; + } + + JSROOT.GridDisplay.prototype = Object.create(JSROOT.MDIDisplay.prototype); + + JSROOT.GridDisplay.prototype.NumGridFrames = function() { + return this.sizex*this.sizey; + } + + JSROOT.GridDisplay.prototype.IsSingle = function() { + return (this.sizex == 1) && (this.sizey == 1); + } + + JSROOT.GridDisplay.prototype.ForEachFrame = function(userfunc, only_visible) { + for (var cnt = 0; cnt < this.sizex * this.sizey; ++cnt) { + var elem = this.IsSingle() ? d3.select("#"+this.frameid) : d3.select("#" + this.frameid + "_grid_" + cnt); + + if (!elem.empty() && elem.attr('frame_title') != '') + JSROOT.CallBack(userfunc, elem.node()); + } + } + + JSROOT.GridDisplay.prototype.CreateFrame = function(title) { + + var main = d3.select("#" + this.frameid); + if (main.empty()) return null; + + var drawid = this.frameid; + + if (!this.IsSingle()) { + var topid = this.frameid + '_grid'; + if (d3.select("#" + topid).empty()) { + var rect = main.node().getBoundingClientRect(); + var h = Math.floor(rect.height / this.sizey) - 1; + var w = Math.floor(rect.width / this.sizex) - 1; + + var content = "
    "+ + ""; + var cnt = 0; + for (var i = 0; i < this.sizey; ++i) { + content += ""; + for (var j = 0; j < this.sizex; ++j) + content += ""; + content += ""; + } + content += "
    "; + + main.html(content); + main.selectAll('.grid_cell').style({ 'width': w + 'px', 'height': h + 'px', 'overflow' : 'hidden'}); + } + + drawid = topid + "_" + this.cnt; + if (++this.cnt >= this.sizex * this.sizey) this.cnt = 0; + } + + JSROOT.cleanup(drawid); + + return d3.select("#" + drawid).html("").attr('frame_title', title).node(); + } + + JSROOT.GridDisplay.prototype.Reset = function() { + JSROOT.MDIDisplay.prototype.Reset.call(this); + if (this.IsSingle()) + d3.select("#" + this.frameid).attr('frame_title', null); + this.cnt = 0; + } + + JSROOT.GridDisplay.prototype.CheckMDIResize = function(frame_id, size) { + + if (!this.IsSingle()) { + var main = d3.select("#" + this.frameid); + var rect = main.node().getBoundingClientRect(); + var h = Math.floor(rect.height / this.sizey) - 1; + var w = Math.floor(rect.width / this.sizex) - 1; + main.selectAll('.grid_cell').style({ 'width': w + 'px', 'height': h + 'px'}); + } + + JSROOT.MDIDisplay.prototype.CheckMDIResize.call(this, frame_id, size); + } + + // ========================================================================= + + JSROOT.RegisterForResize = function(handle, delay) { + // function used to react on browser window resize event + // While many resize events could come in short time, + // resize will be handled with delay after last resize event + // handle can be function or object with CheckResize function + // one could specify delay after which resize event will be handled + + if ((handle===null) || (handle === undefined)) return; + + var myInterval = null, myDelay = delay ? delay : 300; + + if (myDelay < 20) myDelay = 20; + + function ResizeTimer() { + myInterval = null; + + document.body.style.cursor = 'wait'; + if (typeof handle == 'function') handle(); else + if ((typeof handle == 'object') && (typeof handle.CheckResize == 'function')) handle.CheckResize(); else + if (typeof handle == 'string') { + var node = d3.select('#'+handle); + if (!node.empty()) { + var mdi = node.property('mdi'); + if (mdi) { + mdi.CheckMDIResize(); + } else { + JSROOT.resize(node.node()); + } + } + } + document.body.style.cursor = 'auto'; + } + + function ProcessResize() { + if (myInterval !== null) clearTimeout(myInterval); + myInterval = setTimeout(ResizeTimer, myDelay); + } + + window.addEventListener('resize', ProcessResize); + } + + JSROOT.addDrawFunc({ name: "TCanvas", icon: "img_canvas", func: JSROOT.Painter.drawCanvas }); + JSROOT.addDrawFunc({ name: "TPad", icon: "img_canvas", func: JSROOT.Painter.drawPad }); + JSROOT.addDrawFunc({ name: "TSlider", icon: "img_canvas", func: JSROOT.Painter.drawPad }); + JSROOT.addDrawFunc({ name: "TFrame", icon: "img_frame", func: JSROOT.Painter.drawFrame }); + JSROOT.addDrawFunc({ name: "TPaveText", icon: "img_pavetext", func: JSROOT.Painter.drawPaveText }); + JSROOT.addDrawFunc({ name: "TPaveStats", icon: "img_pavetext", func: JSROOT.Painter.drawPaveText }); + JSROOT.addDrawFunc({ name: "TPaveLabel", icon: "img_pavelabel", func: JSROOT.Painter.drawPaveText }); + JSROOT.addDrawFunc({ name: "TLatex", icon:"img_text", func: JSROOT.Painter.drawText }); + JSROOT.addDrawFunc({ name: "TMathText", icon:"img_text", func: JSROOT.Painter.drawText }); + JSROOT.addDrawFunc({ name: "TText", icon:"img_text", func: JSROOT.Painter.drawText }); + JSROOT.addDrawFunc({ name: /^TH1/, icon: "img_histo1d", func: JSROOT.Painter.drawHistogram1D, opt:";hist;P;P0;E;E1;E2;same"}); + JSROOT.addDrawFunc({ name: "TProfile", icon: "img_profile", func: JSROOT.Painter.drawHistogram1D, opt:";E0;E1;E2;p;hist"}); + JSROOT.addDrawFunc({ name: "TH2Poly", icon: "img_histo2d" }); // not yet supported + JSROOT.addDrawFunc({ name: /^TH2/, icon: "img_histo2d", prereq: "more2d", func: "JSROOT.Painter.drawHistogram2D", opt:";COL;COLZ;COL0Z;BOX;SCAT;TEXT;LEGO;LEGO0;LEGO1;LEGO2;LEGO3;LEGO4;same" }); + JSROOT.addDrawFunc({ name: /^TH3/, icon: 'img_histo3d', prereq: "3d", func: "JSROOT.Painter.drawHistogram3D" }); + JSROOT.addDrawFunc({ name: "THStack", prereq: "more2d", func: "JSROOT.Painter.drawHStack" }); + JSROOT.addDrawFunc({ name: "TPolyMarker3D", icon: 'img_histo3d', prereq: "3d", func: "JSROOT.Painter.drawPolyMarker3D" }); + JSROOT.addDrawFunc({ name: "TGraphPolargram" }); // just dummy entry to avoid drawing of this object + JSROOT.addDrawFunc({ name: /^TGraph/, icon:"img_graph", prereq: "more2d", func: "JSROOT.Painter.drawGraph", opt:";L;P"}); + JSROOT.addDrawFunc({ name: "TCutG", icon:"img_graph", prereq: "more2d", func: "JSROOT.Painter.drawGraph", opt:";L;P"}); + JSROOT.addDrawFunc({ name: /^RooHist/, icon:"img_graph", prereq: "more2d", func: "JSROOT.Painter.drawGraph", opt:";L;P" }); + JSROOT.addDrawFunc({ name: /^RooCurve/, icon:"img_graph", prereq: "more2d", func: "JSROOT.Painter.drawGraph", opt:";L;P" }); + JSROOT.addDrawFunc({ name: "TMultiGraph", icon:"img_mgraph", prereq: "more2d", func: "JSROOT.Painter.drawMultiGraph" }); + JSROOT.addDrawFunc({ name: "TStreamerInfoList", icon:'img_question', func: JSROOT.Painter.drawStreamerInfo }); + JSROOT.addDrawFunc({ name: "TPaletteAxis", icon: "img_colz", prereq: "more2d", func: "JSROOT.Painter.drawPaletteAxis" }); + JSROOT.addDrawFunc({ name: "kind:Text", icon:"img_text", func: JSROOT.Painter.drawRawText }); + JSROOT.addDrawFunc({ name: "TF1", icon: "img_graph", prereq: "math;more2d", func: "JSROOT.Painter.drawFunction" }); + JSROOT.addDrawFunc({ name: "TEllipse", icon: 'img_graph', prereq: "more2d", func: "JSROOT.Painter.drawEllipse" }); + JSROOT.addDrawFunc({ name: "TLine", icon: 'img_graph', prereq: "more2d", func: "JSROOT.Painter.drawLine" }); + JSROOT.addDrawFunc({ name: "TArrow", icon: 'img_graph', prereq: "more2d", func: "JSROOT.Painter.drawArrow" }); + JSROOT.addDrawFunc({ name: "TGaxis", icon: "img_graph", func: JSROOT.drawGaxis }); + JSROOT.addDrawFunc({ name: "TLegend", icon: "img_pavelabel", prereq: "more2d", func: "JSROOT.Painter.drawLegend" }); + JSROOT.addDrawFunc({ name: "TBox", icon: 'img_graph', prereq: "more2d", func: "JSROOT.Painter.drawBox" }); + JSROOT.addDrawFunc({ name: "TWbox", icon: 'img_graph', prereq: "more2d", func: "JSROOT.Painter.drawBox" }); + JSROOT.addDrawFunc({ name: "TSliderBox", icon: 'img_graph', prereq: "more2d", func: "JSROOT.Painter.drawBox" }); + JSROOT.addDrawFunc({ name: "TGeoVolume", icon: 'img_histo3d', prereq: "geom", func: "JSROOT.Painter.drawGeoObject", expand: "JSROOT.GEO.expandObject", opt:";more;all;count" }); + JSROOT.addDrawFunc({ name: "TEveGeoShapeExtract", icon: 'img_histo3d', prereq: "geom", func: "JSROOT.Painter.drawGeoObject", expand: "JSROOT.GEO.expandObject", opt: ";more;all;count" }); + JSROOT.addDrawFunc({ name: "TGeoManager", icon: 'img_histo3d', prereq: "geom", expand: "JSROOT.GEO.expandObject", func: "JSROOT.Painter.drawGeoObject", opt: ";more;all;count", dflt: "expand" }); + JSROOT.addDrawFunc({ name: /^TGeo/, icon: 'img_histo3d', prereq: "geom", func: "JSROOT.Painter.drawGeoObject", opt: ";more;all;axis;compa;count" }); + // these are not draw functions, but provide extra info about correspondent classes + JSROOT.addDrawFunc({ name: "kind:Command", icon: "img_execute", execute: true }); + JSROOT.addDrawFunc({ name: "TFolder", icon: "img_folder", icon2: "img_folderopen", noinspect: true, expand: JSROOT.Painter.FolderHierarchy }); + JSROOT.addDrawFunc({ name: "TTask", icon: "img_task", expand: JSROOT.Painter.TaskHierarchy, for_derived: true }); + JSROOT.addDrawFunc({ name: "TTree", icon: "img_tree", noinspect:true, expand: JSROOT.Painter.TreeHierarchy }); + JSROOT.addDrawFunc({ name: "TNtuple", icon: "img_tree", noinspect:true, expand: JSROOT.Painter.TreeHierarchy }); + JSROOT.addDrawFunc({ name: "TBranch", icon: "img_branch", noinspect:true }); + JSROOT.addDrawFunc({ name: /^TLeaf/, icon: "img_leaf", noinspect:true }); + JSROOT.addDrawFunc({ name: "TList", icon: "img_list", noinspect:true, expand: JSROOT.Painter.ListHierarchy }); + JSROOT.addDrawFunc({ name: "TObjArray", icon: "img_list", noinspect:true, expand: JSROOT.Painter.ListHierarchy }); + JSROOT.addDrawFunc({ name: "TClonesArray", icon: "img_list", noinspect:true, expand: JSROOT.Painter.ListHierarchy }); + JSROOT.addDrawFunc({ name: "TColor", icon: "img_color" }); + JSROOT.addDrawFunc({ name: "TFile", icon: "img_file", noinspect:true }); + JSROOT.addDrawFunc({ name: "TMemFile", icon: "img_file", noinspect:true }); + JSROOT.addDrawFunc({ name: "Session", icon: "img_globe" }); + JSROOT.addDrawFunc({ name: "kind:TopFolder", icon: "img_base" }); + JSROOT.addDrawFunc({ name: "kind:Folder", icon: "img_folder", icon2: "img_folderopen", noinspect:true }); + + JSROOT.getDrawHandle = function(kind, selector) { + // return draw handle for specified item kind + // kind could be ROOT.TH1I for ROOT classes or just + // kind string like "Command" or "Text" + // selector can be used to search for draw handle with specified option (string) + // or just sequence id + + if (typeof kind != 'string') return null; + if (selector === "") selector = null; + + var first = null; + + if ((selector === null) && (kind in JSROOT.DrawFuncs.cache)) + return JSROOT.DrawFuncs.cache[kind]; + + var search = (kind.indexOf("ROOT.")==0) ? kind.substr(5) : "kind:"+kind; + + var counter = 0; + for (var i=0; i < JSROOT.DrawFuncs.lst.length; ++i) { + var h = JSROOT.DrawFuncs.lst[i]; + if (typeof h.name == "string") { + if (h.name != search) continue; + } else { + if (!search.match(h.name)) continue; + } + + if (selector==null) { + // store found handle in cache, can reuse later + if (!(kind in JSROOT.DrawFuncs.cache)) JSROOT.DrawFuncs.cache[kind] = h; + return h; + } else + if (typeof selector == 'string') { + if (!first) first = h; + // if drawoption specified, check it present in the list + + if (selector == "::expand") { + if ('expand' in h) return h; + } else + if ('opt' in h) { + var opts = h.opt.split(';'); + for (var j=0; j < opts.length; ++j) opts[j] = opts[j].toLowerCase(); + if (opts.indexOf(selector.toLowerCase())>=0) return h; + } + } else { + if (selector === counter) return h; + } + ++counter; + } + + return first; + } + + JSROOT.addStreamerInfos = function(lst) { + if (lst === null) return; + + function CheckBaseClasses(si, lvl) { + if (si.fElements == null) return null; + if (lvl>10) return null; // protect against recursion + + for (var j=0; j 0) { + + // special handling for painters, which should be loaded via extra scripts + // such painter get extra last argument - pointer on dummy painter object + if (handle.painter_kind === undefined) + handle.painter_kind = (funcname.indexOf("JSROOT.Painter")==0) ? "object" : "base"; + + painter = (handle.painter_kind == "base") ? new JSROOT.TBasePainter() : new JSROOT.TObjectPainter(obj); + + JSROOT.AssertPrerequisites(prereq, function() { + var func = JSROOT.findFunction(funcname); + if (!func) { + alert('Fail to find function ' + funcname + ' after loading ' + prereq); + } else { + handle.func = func; // remember function once it found + + if (performDraw() !== painter) + alert('Painter function ' + funcname + ' do not follow rules of dynamicaly loaded painters'); + } + }); + + return painter; + } + + // try to find function without prerequisisties + var func = JSROOT.findFunction(funcname); + if (func) { + handle.func = func; // remember function once it is found + return performDraw(); + } + + return null; + } + + /** @fn JSROOT.redraw(divid, obj, opt) + * Redraw object in specified HTML element with given draw options + * If drawing was not exists, it will be performed with JSROOT.draw. + * If drawing was already done, that content will be updated */ + + JSROOT.redraw = function(divid, obj, opt) { + if (obj==null) return; + + var dummy = new JSROOT.TObjectPainter(); + dummy.SetDivId(divid, -1); + var can_painter = dummy.pad_painter(); + + if (can_painter !== null) { + if (obj._typename === "TCanvas") { + can_painter.RedrawObject(obj); + return can_painter; + } + + for (var i = 0; i < can_painter.painters.length; ++i) { + var painter = can_painter.painters[i]; + if (painter.MatchObjectType(obj._typename)) + if (painter.UpdateObject(obj)) { + can_painter.RedrawPad(); + return painter; + } + } + } + + if (can_painter) + JSROOT.console("Cannot find painter to update object of type " + obj._typename); + + JSROOT.cleanup(divid); + + return JSROOT.draw(divid, obj, opt); + } + + // Check resize of drawn element + // As first argument divid one should use same argment as for the drawing + // As second argument, one could specify "true" value to force redrawing of + // the element even after minimal resize of the element + // Or one just supply object with exact sizes like { width:300, height:200, force:true }; + + JSROOT.resize = function(divid, arg) { + + if (arg === true) arg = { force: true }; else + if (typeof arg !== 'object') arg = null; + var dummy = new JSROOT.TObjectPainter(), done = false; + dummy.SetDivId(divid, -1); + dummy.ForEachPainter(function(painter) { + if (!done && typeof painter.CheckResize == 'function') + done = painter.CheckResize(arg); + }); + } + + // for compatibility, keep old name + JSROOT.CheckElementResize = JSROOT.resize; + + // safely remove all JSROOT objects from specified element + JSROOT.cleanup = function(divid) { + var dummy = new JSROOT.TObjectPainter(); + dummy.SetDivId(divid, -1); + dummy.ForEachPainter(function(painter) { + if (typeof painter.Cleanup === 'function') + painter.Cleanup(); + }); + dummy.select_main().html(""); + } + + // function to display progress message in the left bottom corner + // previous message will be overwritten + // if no argument specified, any shown messages will be removed + JSROOT.progress = function(msg) { + var id = "jsroot_progressbox"; + var box = d3.select("#"+id); + + if (!JSROOT.gStyle.ProgressBox) return box.remove(); + + if ((arguments.length == 0) || (msg === undefined) || (msg === null)) + return box.remove(); + + if (box.empty()) { + box = d3.select(document.body) + .append("div") + .attr("id", id); + box.append("p"); + } + + box.select("p").html(msg); + } + + return JSROOT; + +})); diff --git a/visualisations/JsRoot460/scripts/JSRootPainter.min.js b/visualisations/JsRoot460/scripts/JSRootPainter.min.js new file mode 100644 index 0000000..2df9521 --- /dev/null +++ b/visualisations/JsRoot460/scripts/JSRootPainter.min.js @@ -0,0 +1 @@ +(function(a){if(typeof define==="function"&&define.amd){define(["JSRootCore","d3"],a)}else{if(typeof JSROOT=="undefined"){throw new Error("JSROOT is not defined","JSRootPainter.js")}if(typeof d3!="object"){throw new Error("d3 is not defined","JSRootPainter.js")}if(typeof JSROOT.Painter=="object"){throw new Error("JSROOT.Painter already defined","JSRootPainter.js")}a(JSROOT,d3)}}(function(a,b){if(typeof define==="function"&&define.amd){a.loadScript("$$$style/JSRootPainter.css")}a.DrawFuncs={lst:[],cache:{}};a.addDrawFunc=function(c,d,e){if((arguments.length==1)&&(typeof arguments[0]=="object")){a.DrawFuncs.lst.push(arguments[0]);return arguments[0]}var f={name:c,func:d,opt:e};a.DrawFuncs.lst.push(f);return f};a.ToolbarIcons={camera:{path:"M 152.00,304.00c0.00,57.438, 46.562,104.00, 104.00,104.00s 104.00-46.562, 104.00-104.00s-46.562-104.00-104.00-104.00S 152.00,246.562, 152.00,304.00z M 480.00,128.00L 368.00,128.00 c-8.00-32.00-16.00-64.00-48.00-64.00L 192.00,64.00 c-32.00,0.00-40.00,32.00-48.00,64.00L 32.00,128.00 c-17.60,0.00-32.00,14.40-32.00,32.00l0.00,288.00 c0.00,17.60, 14.40,32.00, 32.00,32.00l 448.00,0.00 c 17.60,0.00, 32.00-14.40, 32.00-32.00L 512.00,160.00 C 512.00,142.40, 497.60,128.00, 480.00,128.00z M 256.00,446.00c-78.425,0.00-142.00-63.574-142.00-142.00c0.00-78.425, 63.575-142.00, 142.00-142.00c 78.426,0.00, 142.00,63.575, 142.00,142.00 C 398.00,382.426, 334.427,446.00, 256.00,446.00z M 480.00,224.00l-64.00,0.00 l0.00-32.00 l 64.00,0.00 L 480.00,224.00 z"},disk:{path:"M384,0H128H32C14.336,0,0,14.336,0,32v448c0,17.656,14.336,32,32,32h448c17.656,0,32-14.344,32-32V96L416,0H384z M352,160 V32h32v128c0,17.664-14.344,32-32,32H160c-17.664,0-32-14.336-32-32V32h128v128H352z M96,288c0-17.656,14.336-32,32-32h256 c17.656,0,32,14.344,32,32v192H96V288z"},question:{path:"M256,512c141.375,0,256-114.625,256-256S397.375,0,256,0S0,114.625,0,256S114.625,512,256,512z M256,64 c63.719,0,128,36.484,128,118.016c0,47.453-23.531,84.516-69.891,110.016C300.672,299.422,288,314.047,288,320 c0,17.656-14.344,32-32,32c-17.664,0-32-14.344-32-32c0-40.609,37.25-71.938,59.266-84.031 C315.625,218.109,320,198.656,320,182.016C320,135.008,279.906,128,256,128c-30.812,0-64,20.227-64,64.672 c0,17.664-14.336,32-32,32s-32-14.336-32-32C128,109.086,193.953,64,256,64z M256,449.406c-18.211,0-32.961-14.75-32.961-32.969 c0-18.188,14.75-32.953,32.961-32.953c18.219,0,32.969,14.766,32.969,32.953C288.969,434.656,274.219,449.406,256,449.406z"},undo:{path:"M450.159,48.042c8.791,9.032,16.983,18.898,24.59,29.604c7.594,10.706,14.146,22.207,19.668,34.489 c5.509,12.296,9.82,25.269,12.92,38.938c3.113,13.669,4.663,27.834,4.663,42.499c0,14.256-1.511,28.863-4.532,43.822 c-3.009,14.952-7.997,30.217-14.953,45.795c-6.955,15.577-16.202,31.52-27.755,47.826s-25.88,32.9-42.942,49.807 c-5.51,5.444-11.787,11.67-18.834,18.651c-7.033,6.98-14.496,14.366-22.39,22.168c-7.88,7.802-15.955,15.825-24.187,24.069 c-8.258,8.231-16.333,16.203-24.252,23.888c-18.3,18.13-37.354,37.016-57.191,56.65l-56.84-57.445 c19.596-19.472,38.54-38.279,56.84-56.41c7.75-7.685,15.772-15.604,24.108-23.757s16.438-16.163,24.33-24.057 c7.894-7.893,15.356-15.33,22.402-22.312c7.034-6.98,13.312-13.193,18.821-18.651c22.351-22.402,39.165-44.648,50.471-66.738 c11.279-22.09,16.932-43.567,16.932-64.446c0-15.785-3.217-31.005-9.638-45.671c-6.422-14.665-16.229-28.504-29.437-41.529 c-3.282-3.282-7.358-6.395-12.217-9.325c-4.871-2.938-10.381-5.503-16.516-7.697c-6.121-2.201-12.815-3.992-20.058-5.373 c-7.242-1.374-14.9-2.064-23.002-2.064c-8.218,0-16.802,0.834-25.788,2.507c-8.961,1.674-18.053,4.429-27.222,8.271 c-9.189,3.842-18.456,8.869-27.808,15.089c-9.358,6.219-18.521,13.819-27.502,22.793l-59.92,60.271l93.797,94.058H0V40.91 l93.27,91.597l60.181-60.532c13.376-15.018,27.222-27.248,41.536-36.697c14.308-9.443,28.608-16.776,42.89-21.992 c14.288-5.223,28.505-8.74,42.623-10.557C294.645,0.905,308.189,0,321.162,0c13.429,0,26.389,1.185,38.84,3.562 c12.478,2.377,24.2,5.718,35.192,10.029c11.006,4.311,21.126,9.404,30.374,15.265C434.79,34.724,442.995,41.119,450.159,48.042z"},arrow_right:{path:"M30.796,226.318h377.533L294.938,339.682c-11.899,11.906-11.899,31.184,0,43.084c11.887,11.899,31.19,11.893,43.077,0 l165.393-165.386c5.725-5.712,8.924-13.453,8.924-21.539c0-8.092-3.213-15.84-8.924-21.551L338.016,8.925 C332.065,2.975,324.278,0,316.478,0c-7.802,0-15.603,2.968-21.539,8.918c-11.899,11.906-11.899,31.184,0,43.084l113.391,113.384 H30.796c-16.822,0-30.463,13.645-30.463,30.463C0.333,212.674,13.974,226.318,30.796,226.318z"},arrow_up:{path:"M295.505,629.446V135.957l148.193,148.206c15.555,15.559,40.753,15.559,56.308,0c15.555-15.538,15.546-40.767,0-56.304 L283.83,11.662C276.372,4.204,266.236,0,255.68,0c-10.568,0-20.705,4.204-28.172,11.662L11.333,227.859 c-7.777,7.777-11.666,17.965-11.666,28.158c0,10.192,3.88,20.385,11.657,28.158c15.563,15.555,40.762,15.555,56.317,0 l148.201-148.219v493.489c0,21.993,17.837,39.82,39.82,39.82C277.669,669.267,295.505,651.439,295.505,629.446z"},arrow_diag:{path:"M279.875,511.994c-1.292,0-2.607-0.102-3.924-0.312c-10.944-1.771-19.333-10.676-20.457-21.71L233.97,278.348 L22.345,256.823c-11.029-1.119-19.928-9.51-21.698-20.461c-1.776-10.944,4.031-21.716,14.145-26.262L477.792,2.149 c9.282-4.163,20.167-2.165,27.355,5.024c7.201,7.189,9.199,18.086,5.024,27.356L302.22,497.527 C298.224,506.426,289.397,511.994,279.875,511.994z M118.277,217.332l140.534,14.294c11.567,1.178,20.718,10.335,21.878,21.896 l14.294,140.519l144.09-320.792L118.277,217.332z"},auto_zoom:{path:"M505.441,242.47l-78.303-78.291c-9.18-9.177-24.048-9.171-33.216,0c-9.169,9.172-9.169,24.045,0.006,33.217l38.193,38.188 H280.088V80.194l38.188,38.199c4.587,4.584,10.596,6.881,16.605,6.881c6.003,0,12.018-2.297,16.605-6.875 c9.174-9.172,9.174-24.039,0.011-33.217L273.219,6.881C268.803,2.471,262.834,0,256.596,0c-6.229,0-12.202,2.471-16.605,6.881 l-78.296,78.302c-9.178,9.172-9.178,24.045,0,33.217c9.177,9.171,24.051,9.171,33.21,0l38.205-38.205v155.4H80.521l38.2-38.188 c9.177-9.171,9.177-24.039,0.005-33.216c-9.171-9.172-24.039-9.178-33.216,0L7.208,242.464c-4.404,4.403-6.881,10.381-6.881,16.611 c0,6.227,2.477,12.207,6.881,16.61l78.302,78.291c4.587,4.581,10.599,6.875,16.605,6.875c6.006,0,12.023-2.294,16.61-6.881 c9.172-9.174,9.172-24.036-0.005-33.211l-38.205-38.199h152.593v152.063l-38.199-38.211c-9.171-9.18-24.039-9.18-33.216-0.022 c-9.178,9.18-9.178,24.059-0.006,33.222l78.284,78.302c4.41,4.404,10.382,6.881,16.611,6.881c6.233,0,12.208-2.477,16.611-6.881 l78.302-78.296c9.181-9.18,9.181-24.048,0-33.205c-9.174-9.174-24.054-9.174-33.21,0l-38.199,38.188v-152.04h152.051l-38.205,38.199 c-9.18,9.175-9.18,24.037-0.005,33.211c4.587,4.587,10.596,6.881,16.604,6.881c6.01,0,12.024-2.294,16.605-6.875l78.303-78.285 c4.403-4.403,6.887-10.378,6.887-16.611C512.328,252.851,509.845,246.873,505.441,242.47z"},statbox:{path:"M28.782,56.902H483.88c15.707,0,28.451-12.74,28.451-28.451C512.331,12.741,499.599,0,483.885,0H28.782 C13.074,0,0.331,12.741,0.331,28.451C0.331,44.162,13.074,56.902,28.782,56.902zM483.885,136.845H28.782c-15.708,0-28.451,12.741-28.451,28.451c0,15.711,12.744,28.451,28.451,28.451H483.88 c15.707,0,28.451-12.74,28.451-28.451C512.331,149.586,499.599,136.845,483.885,136.845zM483.885,273.275H28.782c-15.708,0-28.451,12.731-28.451,28.452c0,15.707,12.744,28.451,28.451,28.451H483.88 c15.707,0,28.451-12.744,28.451-28.451C512.337,286.007,499.599,273.275,483.885,273.275zM256.065,409.704H30.492c-15.708,0-28.451,12.731-28.451,28.451c0,15.707,12.744,28.451,28.451,28.451h225.585 c15.707,0,28.451-12.744,28.451-28.451C284.516,422.436,271.785,409.704,256.065,409.704z"}};a.Toolbar=function(c,d){if((c!==undefined)&&(typeof c.append=="function")){this.element=c.append("div").attr("class","jsroot");this.addButtons(d)}};a.Toolbar.prototype.addButtons=function(d){var c=this;this.buttonsNames=[];d.forEach(function(e){var f=c.element.append("div").attr("class","toolbar-group");e.forEach(function(h){var g=h.name;if(!g){throw new Error("must provide button 'name' in button config")}if(c.buttonsNames.indexOf(g)!==-1){throw new Error("button name '"+g+"' is taken")}c.buttonsNames.push(g);c.createButton(f,h)})})};a.Toolbar.prototype.createButton=function(e,c){var f=c.title;if(f===undefined){f=c.name}if(typeof c.click!=="function"){throw new Error("must provide button 'click' function in button config")}var d=e.append("a").attr("class","toolbar-btn").attr("rel","tooltip").attr("data-title",f).on("click",c.click);this.createIcon(d,c.icon||a.ToolbarIcons.question)};a.Toolbar.prototype.createIcon=function(f,d){var e=d.size||512;var i=d.scale||1;var c=f.append("svg:svg").attr("height","1em").attr("width","1em").attr("viewBox",[0,0,e,e].join(" "));if("recs" in d){var h={};for(var j=0;j0)&&(f<113)){a.gStyle.Palette=f}}var d=a.GetUrlOption("embed3d",e);if(d!==null){a.gStyle.Embed3DinSVG=parseInt(d)}var c=a.GetUrlOption("webgl",e);if((c==="0")||(c==="false")){a.gStyle.NoWebGL=true}else{if(c==="ie"){a.gStyle.NoWebGL=!a.browser.isIE}}var h=a.GetUrlOption("geosegm",e);if(h!==null){a.gStyle.GeoGradPerSegm=Math.max(2,parseInt(h))}var i=a.GetUrlOption("geocomp",e);if(i!==null){a.gStyle.GeoCompressComp=(i!=="0")&&(i!=="false")}};a.Painter.Coord={kCARTESIAN:1,kPOLAR:2,kCYLINDRICAL:3,kSPHERICAL:4,kRAPIDITY:5};a.Painter.root_colors=function(){var d=["white","black","red","green","blue","yellow","magenta","cyan","rgb(89,212,84)","rgb(89,84,217)","white"];d[110]="white";var g=[{col:11,str:"c1b7ad4d4d4d6666668080809a9a9ab3b3b3cdcdcde6e6e6f3f3f3cdc8accdc8acc3c0a9bbb6a4b3a697b8a49cae9a8d9c8f83886657b1cfc885c3a48aa9a1839f8daebdc87b8f9a768a926983976e7b857d9ad280809caca6c0d4cf88dfbb88bd9f83c89a7dc08378cf5f61ac8f94a6787b946971d45a549300ff7b00ff6300ff4b00ff3300ff1b00ff0300ff0014ff002cff0044ff005cff0074ff008cff00a4ff00bcff00d4ff00ecff00fffd00ffe500ffcd00ffb500ff9d00ff8500ff6d00ff5500ff3d00ff2600ff0e0aff0022ff003aff0052ff006aff0082ff009aff00b1ff00c9ff00e1ff00f9ff00ffef00ffd700ffbf00ffa700ff8f00ff7700ff6000ff4800ff3000ff1800ff0000"},{col:201,str:"5c5c5c7b7b7bb8b8b8d7d7d78a0f0fb81414ec4848f176760f8a0f14b81448ec4876f1760f0f8a1414b84848ec7676f18a8a0fb8b814ecec48f1f1768a0f8ab814b8ec48ecf176f10f8a8a14b8b848ecec76f1f1"},{col:390,str:"ffffcdffff9acdcd9affff66cdcd669a9a66ffff33cdcd339a9a33666633ffff00cdcd009a9a00666600333300"},{col:406,str:"cdffcd9aff9a9acd9a66ff6666cd66669a6633ff3333cd33339a3333663300ff0000cd00009a00006600003300"},{col:422,str:"cdffff9affff9acdcd66ffff66cdcd669a9a33ffff33cdcd339a9a33666600ffff00cdcd009a9a006666003333"},{col:590,str:"cdcdff9a9aff9a9acd6666ff6666cd66669a3333ff3333cd33339a3333660000ff0000cd00009a000066000033"},{col:606,str:"ffcdffff9affcd9acdff66ffcd66cd9a669aff33ffcd33cd9a339a663366ff00ffcd00cd9a009a660066330033"},{col:622,str:"ffcdcdff9a9acd9a9aff6666cd66669a6666ff3333cd33339a3333663333ff0000cd00009a0000660000330000"},{col:791,str:"ffcd9acd9a669a66339a6600cd9a33ffcd66ff9a00ffcd33cd9a00ffcd00ff9a33cd66006633009a3300cd6633ff9a66ff6600ff6633cd3300ff33009aff3366cd00336600339a0066cd339aff6666ff0066ff3333cd0033ff00cdff9a9acd66669a33669a009acd33cdff669aff00cdff339acd00cdff009affcd66cd9a339a66009a6633cd9a66ffcd00ff6633ffcd00cd9a00ffcd33ff9a00cd66006633009a3333cd6666ff9a00ff9a33ff6600cd3300ff339acdff669acd33669a00339a3366cd669aff0066ff3366ff0033cd0033ff339aff0066cd00336600669a339acd66cdff009aff33cdff009acd00cdffcd9aff9a66cd66339a66009a9a33cdcd66ff9a00ffcd33ff9a00cdcd00ff9a33ff6600cd33006633009a6633cd9a66ff6600ff6633ff3300cd3300ffff339acd00666600339a0033cd3366ff669aff0066ff3366cd0033ff0033ff9acdcd669a9a33669a0066cd339aff66cdff009acd009aff33cdff009a"},{col:920,str:"cdcdcd9a9a9a666666333333"}];for(var f=0;f4096)){continue}var c=a.Painter.MakeColorRGB(e);if(c==null){continue}if(a.Painter.root_colors[d]!=c){a.Painter.root_colors[d]=c}}};a.Painter.root_line_styles=new Array("","","3,3","1,2","3,4,1,4","5,3,1,3","5,3,1,3,1,3,1,3","5,5","5,3,1,3,1,3","20,5","20,10,1,10","1,3");a.Painter.root_markers=new Array(0,100,8,7,0,9,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,103,105,104,0,3,4,2,1,106,6,7,5,102,101);a.Painter.createAttMarker=function(f,d){var e=a.Painter.root_colors[f.fMarkerColor];if((d===null)||(d===undefined)){d=f.fMarkerStyle}var c={x0:0,y0:0,color:e,style:d,size:8,stroke:true,fill:true,marker:"",ndig:0,used:true,changed:false};c.Change=function(h,k,j){this.changed=true;if(h!==undefined){this.color=h}if(k!==undefined){this.style=k}if(j!==undefined){this.size=j}else{j=this.size}this.x0=this.y0=0;this.reset_pos=function(){this.lastx=this.lasty=null};if((this.style===1)||(this.style===777)){this.fill=false;this.marker="h1";this.size=1;this.create=function(o,t){var r=Math.round(o),s=Math.round(t),q="M"+r+","+s+"h1";var p=(this.lastx===null)?q:("m"+(r-this.lastx)+","+(s-this.lasty)+"h1");this.lastx=r+1;this.lasty=s;return(p.length0)&&(this.style=100);switch(this.style){case 1:j=this.size=1;break;case 6:j=this.size=2;break;case 7:j=this.size=3;break;default:this.size=j;j*=8}this.ndig=(j>7)?0:((j>2)?1:2);if(g==6){this.ndig++}var m=(j/2).toFixed(this.ndig),i=j.toFixed(this.ndig);switch(g){case 0:this.x0=-j/2;this.marker="a"+m+","+m+" 0 1,0 "+i+",0a"+m+","+m+" 0 1,0 -"+i+",0z";break;case 1:var n=(j/3).toFixed(c.ndig);this.x0=this.y0=j/6;this.marker="h"+n+"v-"+n+"h-"+n+"v-"+n+"h-"+n+"v"+n+"h-"+n+"v"+n+"h"+n+"v"+n+"h"+n+"z";break;case 2:this.x0=-j/2;this.marker="l"+m+",-"+m+"l"+m+","+m+"l-"+m+","+m+"z";break;case 3:this.x0=this.y0=-j/2;this.marker="v"+i+"h"+i+"v-"+i+"z";break;case 4:this.y0=j/2;this.marker="l-"+m+",-"+i+"h"+i+"z";break;case 5:this.y0=-j/2;this.marker="l-"+m+","+i+"h"+i+"z";break;case 6:this.y0=-j/2;this.marker="l"+(j/3).toFixed(c.ndig)+","+i+"l-"+(5/6*j).toFixed(c.ndig)+",-"+(5/8*j).toFixed(c.ndig)+"h"+i+"l-"+(5/6*j).toFixed(c.ndig)+","+(5/8*j).toFixed(c.ndig)+"z";break;case 7:this.x0=this.y0=-j/2;this.marker="l"+i+","+i+"m0,-"+i+"l-"+i+","+i+"m0,-"+m+"h"+i+"m-"+m+",-"+m+"v"+i;break;case 8:this.y0=-j/2;this.marker="v"+i+"m-"+m+",-"+m+"h"+i;break;case 9:this.x0=this.y0=-j/2;this.marker="l"+i+","+i+"m0,-"+i+"l-"+i+","+i;break;default:this.x0=-j/2;this.marker="l"+m+",-"+m+"l"+m+","+m+"l-"+m+","+m+"z";break}this.create=function(o,p){return"M"+(o+this.x0).toFixed(this.ndig)+","+(p+this.y0).toFixed(this.ndig)+this.marker};return true};c.Apply=function(g){g.style("stroke",this.stroke?this.color:"none");g.style("fill",this.fill?this.color:"none")};c.func=c.Apply.bind(c);c.Change(e,d,f.fMarkerSize);c.changed=false;return c};a.Painter.createAttLine=function(i,g,f){var e=0,c=0,h=0;if(typeof i=="string"){if(i=="black"){e=1;c=1}else{if(i=="none"){c=0}}}else{if(typeof i=="object"){if("fLineColor" in i){e=i.fLineColor}if("fLineWidth" in i){c=i.fLineWidth}if("fLineStyle" in i){h=i.fLineStyle}}else{if((i!==undefined)&&!isNaN(i)){e=i}}}if(g!==undefined){c=g}var d={used:true,color:a.Painter.root_colors[e],width:c,dash:a.Painter.root_line_styles[h]};if((c==0)||(e==0)){d.color="none"}if(f){d.excl_side=0;d.excl_width=0;if(Math.abs(d.width)>99){d.excl_side=(d.width<0)?-1:1;d.excl_width=Math.floor(d.width/100)*5;d.width=d.width%100}d.ChangeExcl=function(j,k){if(k!==undefined){this.excl_width=k}if(j!==undefined){this.excl_side=j;if((this.excl_width===0)&&(this.excl_side!==0)){this.excl_width=20}}this.changed=true}}if((d.color===undefined)&&(e>0)){d.color="lightgrey"}d.Apply=function(j){this.used=true;if(this.color=="none"){j.style("stroke",null);j.style("stroke-width",null);j.style("stroke-dasharray",null)}else{j.style("stroke",this.color);j.style("stroke-width",this.width);if(this.dash&&(this.dash.length>0)){j.style("stroke-dasharray",this.dash)}}};d.Change=function(j,k,l){if(j!==undefined){this.color=j}if(k!==undefined){this.width=k}if(l!==undefined){this.dash=l}this.changed=true};d.func=d.Apply.bind(d);return d};a.Painter.clearCuts=function(c){var f=c.indexOf("[");var e=c.indexOf("]");if((f>=0)&&(e>=0)&&(f0){if(e.charAt(0)==="b"){c.weight="bold"}else{if(e.charAt(0)==="i"){c.style="italic"}else{if(e.charAt(0)==="o"){c.style="oblique"}else{break}}}e=e.substr(1)}if(e=="Symbol"){c.weight=null;c.style=null}c.name=e;c.SetFont=function(g){g.attr("font-family",this.name).attr("font-size",this.size).attr("xml:space","preserve");if(this.weight!=null){g.attr("font-weight",this.weight)}if(this.style!=null){g.attr("font-style",this.style)}};c.asStyle=function(g){return((g!=null)?g:this.size)+"px "+this.name};c.stringWidth=function(i,h){var j=i.append("svg:text").attr("xml:space","preserve").style("opacity",0).text(h);this.SetFont(j);var g=j.node().getBBox().width;j.remove();return g};c.func=c.SetFont.bind(c);return c};a.Painter.chooseTimeFormat=function(d,c){if(d<0.5){return c?"%S.%L":"%M:%S.%L"}if(d<30){return c?"%Mm%S":"%H:%M:%S"}d/=60;if(d<30){return c?"%Hh%M":"%d/%m %H:%M"}d/=60;if(d<12){return c?"%d-%Hh":"%d/%m/%y %Hh"}d/=24;if(d<15.218425){return c?"%d/%m":"%d/%m/%y"}d/=30.43685;if(d<6){return"%d/%m/%y"}d/=12;if(d<2){return c?"%m/%y":"%d/%m/%y"}return"%Y"};a.Painter.getTimeFormat=function(c){var d=c.fTimeFormat.indexOf("%F");if(d>=0){return c.fTimeFormat.substr(0,d)}return c.fTimeFormat};a.Painter.getTimeOffset=function(d){var f=d.fTimeFormat.indexOf("%F");if(f<0){return a.gStyle.TimeOffset}var c=d.fTimeFormat.substr(f+2);if(c=="1995-01-01 00:00:00s0"){return 788918400000}if((c=="0")||(c=="")){return 0}var e=new Date(0);var g=c.indexOf("-");e.setFullYear(c.substr(0,g));c=c.substr(g+1);g=c.indexOf("-");e.setMonth(parseInt(c.substr(0,g))-1);c=c.substr(g+1);g=c.indexOf(" ");e.setDate(c.substr(0,g));c=c.substr(g+1);g=c.indexOf(":");e.setHours(c.substr(0,g));c=c.substr(g+1);g=c.indexOf(":");e.setMinutes(c.substr(0,g));c=c.substr(g+1);g=c.indexOf("s");e.setSeconds(c.substr(0,g));if(g>0){c=c.substr(g+1);e.setMilliseconds(c)}return e.getTime()};a.Painter.formatExp=function(l){var k=l;if(parseFloat(k)==1){return"1"}if(parseFloat(k)==10){return"10"}var k=k.replace("e+","x10@");var k=k.replace("e-","x10@-");var f=k.substring(0,k.indexOf("@"));var g=k.substr(k.indexOf("@"));f=f.replace("@","");g=g.replace("@","");var m,n=g.length;for(var d=0;d1&&h<4){m=String.fromCharCode(176+h)}else{m=String.fromCharCode(8304+h)}}}}g=g.replace(i,m)}f=f.replace("1x","");return f+g};a.Painter.translateExp=function(m){var h=m.match(/\^{[0-9]*}/gi);if(h!=null){var d="";for(var g=0;g1&&k<4){n=String.fromCharCode(176+k)}else{n=String.fromCharCode(8304+k)}}d=d.replace(l,n)}m=m.replace(h[g],d)}}return m};a.Painter.symbols_map={"#alpha":"\u03B1","#beta":"\u03B2","#chi":"\u03C7","#delta":"\u03B4","#varepsilon":"\u03B5","#phi":"\u03C6","#gamma":"\u03B3","#eta":"\u03B7","#iota":"\u03B9","#varphi":"\u03C6","#kappa":"\u03BA","#lambda":"\u03BB","#mu":"\u03BC","#nu":"\u03BD","#omicron":"\u03BF","#pi":"\u03C0","#theta":"\u03B8","#rho":"\u03C1","#sigma":"\u03C3","#tau":"\u03C4","#upsilon":"\u03C5","#varomega":"\u03D6","#omega":"\u03C9","#xi":"\u03BE","#psi":"\u03C8","#zeta":"\u03B6","#Alpha":"\u0391","#Beta":"\u0392","#Chi":"\u03A7","#Delta":"\u0394","#Epsilon":"\u0395","#Phi":"\u03A6","#Gamma":"\u0393","#Eta":"\u0397","#Iota":"\u0399","#vartheta":"\u03D1","#Kappa":"\u039A","#Lambda":"\u039B","#Mu":"\u039C","#Nu":"\u039D","#Omicron":"\u039F","#Pi":"\u03A0","#Theta":"\u0398","#Rho":"\u03A1","#Sigma":"\u03A3","#Tau":"\u03A4","#Upsilon":"\u03A5","#varsigma":"\u03C2","#Omega":"\u03A9","#Xi":"\u039E","#Psi":"\u03A8","#Zeta":"\u0396","#varUpsilon":"\u03D2","#epsilon":"\u03B5","#sqrt":"\u221A","#leq":"\u2264","#/":"\u2044","#infty":"\u221E","#voidb":"\u0192","#club":"\u2663","#diamond":"\u2666","#heart":"\u2665","#spade":"\u2660","#leftrightarrow":"\u2194","#leftarrow":"\u2190","#uparrow":"\u2191","#rightarrow":"\u2192","#downarrow":"\u2193","#circ":"\u02C6","#pm":"\xB1","#doublequote":"\u2033","#geq":"\u2265","#times":"\xD7","#propto":"\u221D","#partial":"\u2202","#bullet":"\u2022","#divide":"\xF7","#neq":"\u2260","#equiv":"\u2261","#approx":"\u2248","#3dots":"\u2026","#cbar":"\u007C","#topbar":"\xAF","#downleftarrow":"\u21B5","#aleph":"\u2135","#Jgothic":"\u2111","#Rgothic":"\u211C","#voidn":"\u2118","#otimes":"\u2297","#oplus":"\u2295","#oslash":"\u2205","#cap":"\u2229","#cup":"\u222A","#supseteq":"\u2287","#supset":"\u2283","#notsubset":"\u2284","#subseteq":"\u2286","#subset":"\u2282","#int":"\u222B","#in":"\u2208","#notin":"\u2209","#angle":"\u2220","#nabla":"\u2207","#oright":"\xAE","#ocopyright":"\xA9","#trademark":"\u2122","#prod":"\u220F","#surd":"\u221A","#upoint":"\u22C5","#corner":"\xAC","#wedge":"\u2227","#vee":"\u2228","#Leftrightarrow":"\u21D4","#Leftarrow":"\u21D0","#Uparrow":"\u21D1","#Rightarrow":"\u21D2","#Downarrow":"\u21D3","#LT":"\x3C","#void1":"\xAE","#copyright":"\xA9","#void3":"\u2122","#sum":"\u2211","#arctop":"","#lbar":"","#arcbottom":"","#void8":"","#bottombar":"\u230A","#arcbar":"","#ltbar":"","#AA":"\u212B","#aa":"\u00E5","#void06":"","#GT":"\x3E","#forall":"\u2200","#exists":"\u2203","#bar":"","#vec":"","#dot":"\u22C5","#hat":"\xB7","#ddot":"","#acute":"acute","#grave":"","#check":"\u2713","#tilde":"\u02DC","#slash":"\u2044","#hbar":"\u0127","#box":"","#Box":"","#parallel":"","#perp":"\u22A5","#odot":"","#left":"","#right":""};a.Painter.translateLaTeX=function(d){var h=d;h=this.translateExp(h);while(h.indexOf("^{o}")!=-1){h=h.replace("^{o}","\xBA")}var f=h.match(/\#sqrt{(.*?)}/gi);if(f!=null){for(var e=0;e0)&&(j==h.lastIndexOf("}{"))){h=h.replace("}{","\n ");h=h.slice(11,h.length-1)}}h=h.replace("^2","\xB2").replace("^3","\xB3");return h};a.Painter.isAnyLatex=function(c){return(c.indexOf("#")>=0)||(c.indexOf("\\")>=0)||(c.indexOf("{")>=0)};a.Painter.translateMath=function(f,e,d){if(e!=2){f=f.replace(/#LT/g,"\\langle");f=f.replace(/#GT/g,"\\rangle");f=f.replace(/#club/g,"\\clubsuit");f=f.replace(/#spade/g,"\\spadesuit");f=f.replace(/#heart/g,"\\heartsuit");f=f.replace(/#diamond/g,"\\diamondsuit");f=f.replace(/#voidn/g,"\\wp");f=f.replace(/#voidb/g,"f");f=f.replace(/#copyright/g,"(c)");f=f.replace(/#ocopyright/g,"(c)");f=f.replace(/#trademark/g,"TM");f=f.replace(/#void3/g,"TM");f=f.replace(/#oright/g,"R");f=f.replace(/#void1/g,"R");f=f.replace(/#3dots/g,"\\ldots");f=f.replace(/#lbar/g,"\\mid");f=f.replace(/#void8/g,"\\mid");f=f.replace(/#divide/g,"\\div");f=f.replace(/#Jgothic/g,"\\Im");f=f.replace(/#Rgothic/g,"\\Re");f=f.replace(/#doublequote/g,'"');f=f.replace(/#plus/g,"+");f=f.replace(/#diamond/g,"\\diamondsuit");f=f.replace(/#voidn/g,"\\wp");f=f.replace(/#voidb/g,"f");f=f.replace(/#copyright/g,"(c)");f=f.replace(/#ocopyright/g,"(c)");f=f.replace(/#trademark/g,"TM");f=f.replace(/#void3/g,"TM");f=f.replace(/#oright/g,"R");f=f.replace(/#void1/g,"R");f=f.replace(/#3dots/g,"\\ldots");f=f.replace(/#lbar/g,"\\mid");f=f.replace(/#void8/g,"\\mid");f=f.replace(/#divide/g,"\\div");f=f.replace(/#Jgothic/g,"\\Im");f=f.replace(/#Rgothic/g,"\\Re");f=f.replace(/#doublequote/g,'"');f=f.replace(/#plus/g,"+");f=f.replace(/#minus/g,"-");f=f.replace(/#\//g,"/");f=f.replace(/#upoint/g,".");f=f.replace(/#aa/g,"\\mathring{a}");f=f.replace(/#AA/g,"\\mathring{A}");f=f.replace(/#omicron/g,"o");f=f.replace(/#Alpha/g,"A");f=f.replace(/#Beta/g,"B");f=f.replace(/#Epsilon/g,"E");f=f.replace(/#Zeta/g,"Z");f=f.replace(/#Eta/g,"H");f=f.replace(/#Iota/g,"I");f=f.replace(/#Kappa/g,"K");f=f.replace(/#Mu/g,"M");f=f.replace(/#Nu/g,"N");f=f.replace(/#Omicron/g,"O");f=f.replace(/#Rho/g,"P");f=f.replace(/#Tau/g,"T");f=f.replace(/#Chi/g,"X");f=f.replace(/#varomega/g,"\\varpi");f=f.replace(/#corner/g,"?");f=f.replace(/#ltbar/g,"?");f=f.replace(/#bottombar/g,"?");f=f.replace(/#notsubset/g,"?");f=f.replace(/#arcbottom/g,"?");f=f.replace(/#cbar/g,"?");f=f.replace(/#arctop/g,"?");f=f.replace(/#topbar/g,"?");f=f.replace(/#arcbar/g,"?");f=f.replace(/#downleftarrow/g,"?");f=f.replace(/#splitline/g,"\\genfrac{}{}{0pt}{}");f=f.replace(/#it/g,"\\textit");f=f.replace(/#bf/g,"\\textbf");f=f.replace(/#frac/g,"\\frac");f=f.replace(/#left{/g,"\\lbrace");f=f.replace(/#right}/g,"\\rbrace");f=f.replace(/#left\[/g,"\\lbrack");f=f.replace(/#right\]/g,"\\rbrack");f=f.replace(/#\[\]{/g,"\\lbrack");f=f.replace(/ } /g,"\\rbrack");f=f.replace(/#\[/g,"\\lbrack");f=f.replace(/#\]/g,"\\rbrack");f=f.replace(/#{/g,"\\lbrace");f=f.replace(/#}/g,"\\rbrace");f=f.replace(/ /g,"\\;");for(var c in a.Painter.symbols_map){var g="\\"+c.substr(1);f=f.replace(new RegExp(c,"g"),g)}}else{f=f.replace(/\\\^/g,"\\hat")}if(typeof d!="string"){return"\\("+f+"\\)"}if(d.indexOf("rgb(")>=0){d=d.replace(/rgb/g,"[RGB]").replace(/\(/g,"{").replace(/\)/g,"}")}return"\\(\\color{"+d+"}"+f+"\\)"};a.TBasePainter=function(){this.divid=null};a.TBasePainter.prototype.Cleanup=function(){};a.TBasePainter.prototype.DrawingReady=function(){this._ready_called_=true;if("_ready_callback_" in this){a.CallBack(this._ready_callback_,this);delete this._ready_callback_}return this};a.TBasePainter.prototype.WhenReady=function(c){if("_ready_called_" in this){return a.CallBack(c,this)}this._ready_callback_=c};a.TBasePainter.prototype.GetObject=function(){return null};a.TBasePainter.prototype.MatchObjectType=function(c){return false};a.TBasePainter.prototype.UpdateObject=function(c){return false};a.TBasePainter.prototype.RedrawPad=function(c){};a.TBasePainter.prototype.RedrawObject=function(d){if(this.UpdateObject(d)){var c=document.body.style.cursor;document.body.style.cursor="wait";this.RedrawPad();document.body.style.cursor=c}};a.TBasePainter.prototype.CheckResize=function(c){return false};a.TBasePainter.prototype.select_main=function(){if((this.divid===null)||(this.divid===undefined)){return b.select(null)}if((typeof this.divid=="string")&&(this.divid.charAt(0)!="#")){return b.select("#"+this.divid)}return b.select(this.divid)};a.TBasePainter.prototype.main_visible_rect=function(){var c=this.select_main();var e=c.node().getBoundingClientRect();var d={};d.width=Math.round(e.width-this.GetStyleValue(c,"padding-left")-this.GetStyleValue(c,"padding-right"));d.height=Math.round(e.height-this.GetStyleValue(c,"padding-top")-this.GetStyleValue(c,"padding-bottom"));return d};a.TBasePainter.prototype.SetDivId=function(e){if(arguments.length>0){this.divid=e}var c=this.select_main();var d=c.node()?c.node().firstChild:null;if(d){d.painter=this}};a.TBasePainter.prototype.SetItemName=function(c,d){if(typeof c==="string"){this._hitemname=c}else{delete this._hitemname}if(typeof d==="string"){this._hdrawopt=d}};a.TBasePainter.prototype.GetItemName=function(){return("_hitemname" in this)?this._hitemname:null};a.TBasePainter.prototype.GetItemDrawOpt=function(){return("_hdrawopt" in this)?this._hdrawopt:""};a.TBasePainter.prototype.CanZoomIn=function(d,e,c){return false};a.TBasePainter.prototype.GetStyleValue=function(c,d){var e=c.style(d);if(!e){return 0}e=parseFloat(e.replace("px",""));return isNaN(e)?0:e};a.TObjectPainter=function(c){a.TBasePainter.call(this);this.draw_g=null;this.pad_name="";this.main=null;this.draw_object=((c!==undefined)&&(typeof c=="object"))?c:null};a.TObjectPainter.prototype=Object.create(a.TBasePainter.prototype);a.TObjectPainter.prototype.GetObject=function(){return this.draw_object};a.TObjectPainter.prototype.MatchObjectType=function(c){if((c===undefined)||(c===null)||(this.draw_object===null)){return false}if(typeof c==="string"){return this.draw_object._typename===c}return(typeof c==="object")&&(this.draw_object._typename===c._typename)};a.TObjectPainter.prototype.SetItemName=function(c,d){a.TBasePainter.prototype.SetItemName.call(this,c,d);if(this.no_default_title||(c=="")){return}var e=this.svg_canvas();if(!e.empty()){e.select("title").text(c)}else{this.select_main().attr("title",c)}};a.TObjectPainter.prototype.UpdateObject=function(c){if(!this.MatchObjectType(c)){return false}a.extend(this.GetObject(),c);return true};a.TObjectPainter.prototype.GetTipName=function(c){var d=this.GetItemName();if(d===null){d=""}if((d.length===0)&&("fName" in this.GetObject())){d=this.GetObject().fName}if(d.lenght>20){d=d.substr(0,17)+"..."}if((d.length>0)&&(c!==undefined)){d+=c}return d};a.TObjectPainter.prototype.pad_painter=function(c){var d=c?this.svg_pad():this.svg_canvas();return d.empty()?null:d.property("pad_painter")};a.TObjectPainter.prototype.CheckResize=function(c){var d=this.pad_painter();if(!d){return false}d.CheckCanvasResize(c);return true};a.TObjectPainter.prototype.RemoveDrawG=function(){if(this.draw_g!=null){this.draw_g.remove();this.draw_g=null}};a.TObjectPainter.prototype.RecreateDrawG=function(c,d){if(this.draw_g){b.selectAll(this.draw_g.node().childNodes).remove()}else{if(c){if(typeof d!="string"){d="text_layer"}if(d.charAt(0)=="."){d=d.substr(1)}this.draw_g=this.svg_layer(d).append("svg:g")}else{if(typeof d!="string"){d=".main_layer"}if(d.charAt(0)!="."){d="."+d}this.draw_g=this.svg_frame().select(d).append("svg:g")}}if(this.draw_object!==null){this.draw_g.attr("objname",this.draw_object.fName);this.draw_g.attr("objtype",this.draw_object._typename)}return this.draw_g};a.TObjectPainter.prototype.svg_canvas=function(){return this.select_main().select(".root_canvas")};a.TObjectPainter.prototype.svg_pad=function(d){var e=this.svg_canvas();if(d===undefined){d=this.pad_name}if((d.length>0)&&!e.empty()){e=e.select(".subpads_layer").select("[pad="+d+"]")}return e};a.TObjectPainter.prototype.svg_layer=function(e,d){var c=this.svg_pad(d);if(c.empty()){return c}var g=c.node().firstChild;while(g!==null){var f=b.select(g);if(f.classed(e)){return f}g=g.nextSibling}return b.select(null)};a.TObjectPainter.prototype.CurrentPadName=function(d){var c=this.svg_canvas();if(c.empty()){return""}var e=c.property("current_pad");if(d!==undefined){c.property("current_pad",d)}return e};a.TObjectPainter.prototype.root_pad=function(){var c=this.pad_painter(true);return c?c.pad:null};a.TObjectPainter.prototype.ConvertToNDC=function(d,e,c){var f=this.root_pad();if(c==null){c=false}if(c||(f==null)){return e}if(d=="y"){if(f.fLogy){e=(e>0)?a.log10(e):f.fUymin}return(e-f.fY1)/(f.fY2-f.fY1)}if(f.fLogx){e=(e>0)?a.log10(e):f.fUxmin}return(e-f.fX1)/(f.fX2-f.fX1)};a.TObjectPainter.prototype.AxisToSvg=function(e,f,d){var c=this.main_painter();if((c!=null)&&!d){return e=="y"?c.gry(f):c.grx(f)}if(!d){f=this.ConvertToNDC(e,f)}if(e=="y"){return(1-f)*this.pad_height()}return f*this.pad_width()};a.TObjectPainter.prototype.PadToSvg=function(d,e,c){return this.AxisToSvg(d,e,c)};a.TObjectPainter.prototype.svg_frame=function(){return this.svg_pad().select(".root_frame")};a.TObjectPainter.prototype.frame_painter=function(){var c=this.svg_frame().property("frame_painter");return(c===undefined)?null:c};a.TObjectPainter.prototype.pad_width=function(c){var d=this.svg_pad(c).property("draw_width");return isNaN(d)?0:d};a.TObjectPainter.prototype.pad_height=function(c){var d=this.svg_pad(c).property("draw_height");return isNaN(d)?0:d};a.TObjectPainter.prototype.frame_x=function(){var c=parseInt(this.svg_frame().attr("x"));return isNaN(c)?0:c};a.TObjectPainter.prototype.frame_y=function(){var c=parseInt(this.svg_frame().attr("y"));return isNaN(c)?0:c};a.TObjectPainter.prototype.frame_width=function(){var c=parseInt(this.svg_frame().attr("width"));return isNaN(c)?0:c};a.TObjectPainter.prototype.frame_height=function(){var c=parseInt(this.svg_frame().attr("height"));return isNaN(c)?0:c};a.TObjectPainter.prototype.embed_3d=function(){if(a.gStyle.Embed3DinSVG<2){return a.gStyle.Embed3DinSVG}if(a.browser.isFirefox){return a.gStyle.Embed3DinSVG}return 1};a.TObjectPainter.prototype.access_3d_kind=function(d){var c=this.svg_pad();if(c.empty()){return -1}var e=c.property("can3d");if(d!==undefined){c.property("can3d",d)}return((e===null)||(e===undefined))?-1:e};a.TObjectPainter.prototype.size_for_3d=function(g){if(g===undefined){g=this.embed_3d()}var h=this.svg_pad();var d=this.pad_name;if(d==""){d="canvas"}d="draw3d_"+d;if(h.empty()){var f=this.main_visible_rect();if((f.height<10)&&(f.width>10)){f.height=Math.round(0.66*f.width);this.select_main().style("height",f.height+"px")}f.x=0;f.y=0;f.clname=d;f.can3d=-1;return f}var e=h;if(g==0){e=this.svg_canvas()}var c={x:0,y:0,width:100,height:100,clname:d,can3d:g};if(this.frame_painter()!==null){e=this.svg_frame();c.x=e.property("draw_x");c.y=e.property("draw_y")}c.width=e.property("draw_width");c.height=e.property("draw_height");if((this.frame_painter()===null)&&(g>0)){c.x=Math.round(c.x+c.width*0.1);c.y=Math.round(c.y+c.height*0.1);c.width=Math.round(c.width*0.8);c.height=Math.round(c.height*0.8)}if(g===1){this.CalcAbsolutePosition(this.svg_pad(),c)}return c};a.TObjectPainter.prototype.clear_3d_canvas=function(){var d=this.access_3d_kind(null);if(d<0){return}var c=this.size_for_3d(d);if(c.can3d===0){b.select(this.svg_canvas().node().nextSibling).remove();this.svg_canvas().style("display",null)}else{if(this.svg_pad().empty()){return}this.apply_3d_size(c).remove();this.svg_frame().style("display",null)}};a.TObjectPainter.prototype.add_3d_canvas=function(d,f){if((f==null)||(d.can3d<-1)){return}if(d.can3d===-1){var c=this.select_main().node();if(c!==null){c.appendChild(f);f.painter=this}return}this.access_3d_kind(d.can3d);if(d.can3d===0){this.svg_canvas().style("display","none");this.svg_canvas().node().parentNode.appendChild(f)}else{if(this.svg_pad().empty()){return}this.svg_frame().style("display","none");var e=this.apply_3d_size(d);e.attr("title","").node().appendChild(f)}};a.TObjectPainter.prototype.apply_3d_size=function(g,i){if(g.can3d<0){return b.select(null)}var h;if(g.can3d>1){var f=this.svg_layer("special_layer");h=f.select("."+g.clname);if(i){return h}if(h.empty()){h=f.append("foreignObject").attr("class",g.clname)}h.attr("x",g.x).attr("y",g.y).attr("width",g.width).attr("height",g.height).attr("viewBox","0 0 "+g.width+" "+g.height).attr("preserveAspectRatio","xMidYMid")}else{var e=this.svg_canvas().node().parentNode;h=b.select(e).select("."+g.clname);if(i){return h}this.svg_canvas().property("redraw_by_resize",true);if(h.empty()){h=b.select(e).append("div").attr("class",g.clname)}var d=0,c=0;while(e&&!d&&!c){if(getComputedStyle(e).position!=="static"){break}d+=e.offsetLeft;c+=e.offsetTop;e=e.parentNode}h.style("position","absolute").style("left",(g.x+d)+"px").style("top",(g.y+c)+"px").style("width",g.width+"px").style("height",g.height+"px")}return h};a.TObjectPainter.prototype.main_painter=function(){if(this.main===null){var c=this.svg_pad();if(!c.empty()){this.main=c.property("mainpainter");if(this.main===undefined){this.main=null}}}return this.main};a.TObjectPainter.prototype.is_main_painter=function(){return this===this.main_painter()};a.TObjectPainter.prototype.SetDivId=function(h,g,f){if(h!==undefined){this.divid=h}if((g===null)||(g===undefined)){g=0}this.create_canvas=false;var e=this.svg_canvas();if(e.empty()&&(g>0)&&(g!==5)){a.Painter.drawCanvas(h,null,((g==2)||(g==4))?"noframe":"");e=this.svg_canvas();this.create_canvas=true}if(e.empty()){if((g<0)||(g===5)||this.iscan){return}var c=this.select_main();if(c.node()&&c.node().firstChild){c.node().firstChild.painter=this}return}this.pad_name=f;if(this.pad_name===undefined){this.pad_name=this.CurrentPadName()}if(g<0){return}if(this.svg_frame().select(".main_layer").empty()&&((g==1)||(g==3))){a.Painter.drawFrame(h,null);if(this.svg_frame().empty()){return alert("Fail to draw dummy TFrame")}}var d=this.svg_pad();if(d.empty()){return}if(d.property("pad_painter")!==this){d.property("pad_painter").painters.push(this)}if(((g===1)||(g===4)||(g===5))&&!d.property("mainpainter")){d.property("mainpainter",this)}};a.TObjectPainter.prototype.CalcAbsolutePosition=function(c,d){while(!c.empty()&&!c.classed("root_canvas")){if(c.classed("root_frame")||c.classed("root_pad")){d.x+=c.property("draw_x");d.y+=c.property("draw_y")}c=b.select(c.node().parentNode)}return d};a.TObjectPainter.prototype.createAttFill=function(e,f,c,d){var g={color:"none",colorindx:0,pattern:0,used:true,kind:2,changed:false};if(d!==undefined){g.kind=d}g.Apply=function(h){this.used=true;h.style("fill",this.color);if("opacity" in this){h.style("opacity",this.opacity)}if("antialias" in this){h.style("antialias",this.antialias)}};g.func=g.Apply.bind(g);g.Change=function(j,m,i){this.changed=true;if((j!==undefined)&&!isNaN(j)){this.colorindx=j}if((m!==undefined)&&!isNaN(m)){this.pattern=m;delete this.opacity;delete this.antialias}if(this.pattern<1001){this.color="none";return true}if((this.pattern===1001)&&(this.colorindx===0)&&(this.kind===1)){this.color="none";return true}this.color=a.Painter.root_colors[this.colorindx];if(typeof this.color!="string"){this.color="none"}if(this.pattern===1001){return true}if((this.pattern>=4000)&&(this.pattern<=4100)){this.opacity=(this.pattern-4000)/100;return true}if((i===undefined)||i.empty()||(this.pattern<3000)||(this.pattern>3025)){return false}var n="pat_"+this.pattern+"_"+this.colorindx;var h=i.select("defs");if(h.empty()){h=i.insert("svg:defs",":first-child")}var k=this.color;this.color="url(#"+n+")";this.antialias=false;if(!h.select("."+n).empty()){return true}var l=h.append("svg:pattern").attr("id",n).attr("class",n).attr("patternUnits","userSpaceOnUse");switch(this.pattern){case 3001:l.attr("width",2).attr("height",2);l.append("svg:rect").attr("x",0).attr("y",0).attr("width",1).attr("height",1);l.append("svg:rect").attr("x",1).attr("y",1).attr("width",1).attr("height",1);break;case 3002:l.attr("width",4).attr("height",2);l.append("svg:rect").attr("x",1).attr("y",0).attr("width",1).attr("height",1);l.append("svg:rect").attr("x",3).attr("y",1).attr("width",1).attr("height",1);break;case 3003:l.attr("width",4).attr("height",4);l.append("svg:rect").attr("x",2).attr("y",1).attr("width",1).attr("height",1);l.append("svg:rect").attr("x",0).attr("y",3).attr("width",1).attr("height",1);break;case 3005:l.attr("width",8).attr("height",8);l.append("svg:line").attr("x1",0).attr("y1",0).attr("x2",8).attr("y2",8);break;case 3006:l.attr("width",4).attr("height",4);l.append("svg:line").attr("x1",1).attr("y1",0).attr("x2",1).attr("y2",3);break;case 3007:l.attr("width",4).attr("height",4);l.append("svg:line").attr("x1",0).attr("y1",1).attr("x2",3).attr("y2",1);break;case 3010:l.attr("width",10).attr("height",10);l.append("svg:line").attr("x1",0).attr("y1",2).attr("x2",10).attr("y2",2);l.append("svg:line").attr("x1",0).attr("y1",7).attr("x2",10).attr("y2",7);l.append("svg:line").attr("x1",2).attr("y1",0).attr("x2",2).attr("y2",2);l.append("svg:line").attr("x1",7).attr("y1",2).attr("x2",7).attr("y2",7);l.append("svg:line").attr("x1",2).attr("y1",7).attr("x2",2).attr("y2",10);break;case 3021:case 3022:l.attr("width",10).attr("height",10);l.append("svg:line").attr("x1",0).attr("y1",5).attr("x2",5).attr("y2",5);l.append("svg:line").attr("x1",5).attr("y1",5).attr("x2",5).attr("y2",0);l.append("svg:line").attr("x1",5).attr("y1",10).attr("x2",10).attr("y2",10);l.append("svg:line").attr("x1",10).attr("y1",10).attr("x2",10).attr("y2",5);break;default:l.attr("width",8).attr("height",8);l.append("svg:line").attr("x1",8).attr("y1",0).attr("x2",0).attr("y2",8);break}l.selectAll("line").style("stroke",k).style("stroke-width",1);l.selectAll("rect").style("fill",k);return true};if((e!==null)&&(typeof e=="object")){if("fFillStyle" in e){f=e.fFillStyle}if("fFillColor" in e){c=e.fFillColor}}g.Change(c,f,this.svg_canvas());g.changed=false;return g};a.TObjectPainter.prototype.ForEachPainter=function(f){var c=this.select_main();var d=(c.node()&&c.node().firstChild)?c.node().firstChild.painter:null;if(d!=null){return f(d)}var g=this.pad_painter(true);if(g==null){return}f(g);if("painters" in g){for(var e=0;e0)){r+=u;u=0;if(r>0){u=r;r=0}}if((r>0)&&(u<0)){r+=u;u=0;if(r<0){u=r;r=0}}if((p<0)&&(t>0)){p+=t;t=0;if(p>0){t=p;p=0}}if((p>0)&&(t<0)){p+=t;t=0;if(p<0){t=p;p=0}}if(s+u<0){r+=(s+u);s=0}else{if(s+u>k){r+=(s+u-k);s=k}else{s+=u}}if(v+t<0){p+=(v+t);v=0}else{if(v+t>e){p+=(v+t-e);v=e}else{v+=t}}i.attr("x",s).attr("y",v);b.event.sourceEvent.stopPropagation()}).on("dragend",function(){if(i==null){return}b.event.sourceEvent.preventDefault();if(h()===false){if(o.ctxmenu&&((new Date()).getTime()-j.getTime()>600)){var s=f.node().getBoundingClientRect();d.ShowContextMenu("main",{clientX:s.left,clientY:s.top})}}});var l=b.behavior.drag().origin(Object).on("dragstart",function(){if(m(b.event.sourceEvent)){return}b.event.sourceEvent.stopPropagation();b.event.sourceEvent.preventDefault();d.SwitchTooltip(false);r=0;p=0;k=d.pad_width();e=d.pad_height();i=b.select(d.draw_g.node().parentNode).append("rect").classed("zoom",true).attr("x",d.draw_g.attr("x")).attr("y",d.draw_g.attr("y")).attr("width",c()).attr("height",q()).style("cursor",b.select(this).style("cursor"))}).on("drag",function(){if(i==null){return}b.event.sourceEvent.preventDefault();var u=Number(i.attr("width")),z=Number(i.attr("height")),s=Number(i.attr("x")),A=Number(i.attr("y"));var v=b.event.dx,t=b.event.dy;if((r<0)&&(v>0)){r+=v;v=0;if(r>0){v=r;r=0}}if((r>0)&&(v<0)){r+=v;v=0;if(r<0){v=r;r=0}}if((p<0)&&(t>0)){p+=t;t=0;if(p>0){t=p;p=0}}if((p>0)&&(t<0)){p+=t;t=0;if(p<0){t=p;p=0}}if(b.select(this).classed("resize_corner1")){if(s+v<0){r+=(s+v);u+=s;s=0}else{if(u-v<0){r-=(u-v);s+=u;u=0}else{s+=v;u-=v}}if(A+t<0){p+=(A+t);z+=A;A=0}else{if(z-t<0){p-=(z-t);A+=z;z=0}else{A+=t;z-=t}}}else{if(s+u+v>k){r+=(s+u+v-k);u=k-s}else{if(u+v<0){r+=(u+v);u=0}else{u+=v}}if(A+z+t>e){p+=(A+z+t-e);z=e-A}else{if(z+t<0){p+=(z+t);z=0}else{z+=t}}}i.attr("x",s).attr("y",A).attr("width",u).attr("height",z);b.event.sourceEvent.stopPropagation()}).on("dragend",function(){if(i==null){return}b.event.sourceEvent.preventDefault();h()});if(!("only_resize" in o)){this.draw_g.style("cursor","move").call(n)}g.call(l);f.call(l)};a.TObjectPainter.prototype.startTouchMenu=function(e){var c=b.touches(this.svg_frame().node());if(c.length!=1){return}if(!e||(e=="")){e="main"}var d="touch_"+e;b.event.preventDefault();b.event.stopPropagation();this[d]={dt:new Date(),pos:c[0]};this.svg_frame().on("touchcancel",this.endTouchMenu.bind(this,e)).on("touchend",this.endTouchMenu.bind(this,e))};a.TObjectPainter.prototype.endTouchMenu=function(d){var c="touch_"+d;if(!(c in this)){return}b.event.preventDefault();b.event.stopPropagation();var f=new Date().getTime()-this[c].dt.getTime();this.svg_frame().on("touchcancel",null).on("touchend",null);if(f>500){var e=this.svg_frame().node().getBoundingClientRect();this.ShowContextMenu(d,{clientX:e.left+this[c].pos[0],clientY:e.top+this[c].pos[1]})}delete this[c]};a.TObjectPainter.prototype.AddColorMenuEntry=function(e,d,j,i,c){if(j===undefined){return}e.add("sub:"+d,function(){var m=(typeof j!=="string");var l=prompt("Enter color "+(m?"(only id number)":"(name or id)"),j);if(l==null){return}var n=parseInt(l);if(!isNaN(n)&&(a.Painter.root_colors[n]!==undefined)){l=a.Painter.root_colors[n]}else{if(m){return}}i.bind(this)(m?n:l)});var k=(typeof j!=="string");for(var f=-1;f<11;++f){if((f<0)&&k){continue}if((f==10)&&(c!==1)){continue}var g=(f<0)?"none":a.Painter.root_colors[f];if((f==0)&&(c==1)){g="none"}var h=""+g+"";e.addchk((j==(k?f:g)),h,(k?f:g),i)}e.add("endsub:")};a.TObjectPainter.prototype.AddSizeMenuEntry=function(d,c,g,i,f,k,h){if(k===undefined){return}d.add("sub:"+c,function(){var l=k.toFixed(4);if(f>=0.1){l=k.toFixed(2)}if(f>=1){l=k.toFixed(0)}var m=prompt("Enter value of "+c,l);if(m==null){return}var m=parseFloat(m);if(!isNaN(m)){h.bind(this)((f>=1)?Math.round(m):m)}});for(var e=g;e<=i;e+=f){var j=e.toFixed(2);if(f>=0.1){j=e.toFixed(1)}if(f>=1){j=e.toFixed(0)}d.addchk((Math.abs(k-e)10){console.log("Redraw ",Math.round(d/f));f=d=0}g.send("READY")}else{if(o.substr(0,4)=="MENU"){var j=a.parse(o.substr(4));console.log("get MENUS ",typeof j,j.length,o.length-4);g.send("READY");if(typeof c._getmenu_callback=="function"){c._getmenu_callback(j)}}else{console.log("msg",o)}}};g.onclose=function(){console.log("websocket closed");delete c._websocket};g.onerror=function(j){console.log("err",j);g.close()}};a.TObjectPainter.prototype.FillObjectExecMenu=function(f,e){if(!("_websocket" in this)||("_getmenu_callback" in this)){return a.CallBack(e)}function c(g){console.log("execute method "+g);if(this._websocket){this._websocket.send("EXEC"+g)}}function d(j,i,g){if(!this._getmenu_callback){return}delete this._getmenu_callback;if(g&&g.length){j.add("separator");j.add("sub:Online");for(var k=0;k";h.addchk((this.lineatt.dash==f),d,f,function(k){this.lineatt.Change(undefined,undefined,k);this.Redraw()}.bind(this))}h.add("endsub:");h.add("endsub:");if(("excl_side" in this.lineatt)&&(this.lineatt.excl_side!==0)){h.add("sub:Exclusion");h.add("sub:side");for(var e=-1;e<=1;++e){h.addchk((this.lineatt.excl_side==e),e,e,function(k){this.lineatt.ChangeExcl(parseInt(k));this.Redraw()}.bind(this))}h.add("endsub:");this.AddSizeMenuEntry(h,"width",10,100,10,this.lineatt.excl_width,function(k){this.lineatt.ChangeExcl(undefined,parseInt(k));this.Redraw()}.bind(this));h.add("endsub:")}}if(this.fillatt&&this.fillatt.used){h.add("sub:"+g+"Fill att");this.AddColorMenuEntry(h,"color",this.fillatt.colorindx,function(k){this.fillatt.Change(parseInt(k),undefined,this.svg_canvas());this.Redraw()}.bind(this),this.fillatt.kind);h.add("sub:style",function(){var k=prompt("Enter fill style id (1001-solid, 3000..3010)",this.fillatt.pattern);if(k==null){return}k=parseInt(k);if(isNaN(k)){return}this.fillatt.Change(undefined,k,this.svg_canvas());this.Redraw()}.bind(this));var c=[1,1001,3001,3002,3003,3004,3005,3006,3007,3010,3021,3022];var i=a.clone(this.fillatt);if(i.colorindx<=0){i.colorindx=1}for(var j=0;j";h.addchk(this.fillatt.pattern==c[j],d,c[j],function(k){this.fillatt.Change(undefined,parseInt(k),this.svg_canvas());this.Redraw()}.bind(this))}h.add("endsub:");h.add("endsub:")}if(this.markeratt&&this.markeratt.used){h.add("sub:"+g+"Marker att");this.AddColorMenuEntry(h,"color",this.markeratt.color,function(k){this.markeratt.Change(k);this.Redraw()}.bind(this));this.AddSizeMenuEntry(h,"size",0.5,6,0.5,this.markeratt.size,function(k){this.markeratt.Change(undefined,undefined,parseFloat(k));this.Redraw()}.bind(this));h.add("sub:style");var c=[1,2,3,4,5,6,7,8,21,22,23,24,25,26,27,28,29,30,31,32,33,34];var i=a.clone(this.markeratt);for(var j=0;j";h.addchk(this.markeratt.style==c[j],d,c[j],function(k){this.markeratt.Change(undefined,parseInt(k));this.Redraw()}.bind(this))}h.add("endsub:");h.add("endsub:")}};a.TObjectPainter.prototype.TextAttContextMenu=function(g,e){var f=this.GetObject();if(!f||!("fTextColor" in f)){return}g.add("sub:"+(e?e:"Text"));this.AddColorMenuEntry(g,"color",f.fTextColor,function(j){this.GetObject().fTextColor=parseInt(j);this.Redraw()}.bind(this));var i=[11,12,13,21,22,23,31,32,33],d=["left","centered","right"],c=["bottom","centered","top"];g.add("sub:align");for(var h=0;h0};a.TObjectPainter.prototype.FindInPrimitives=function(f){var d=this.pad_painter(true);if((d===null)||(d.pad===null)){return null}if(d.pad.fPrimitives!==null){for(var e=0;ec.property("text_factor"))){c.property("text_factor",d)}};a.TObjectPainter.prototype.GetBoundarySizes=function(e){if(e===null){console.warn("empty node in GetBoundarySizes");return{width:0,height:0}}var d=e.getBoundingClientRect();if(parseInt(d.width)>0){d=e.getBBox()}var c={width:parseInt(d.width),height:parseInt(d.height)};if("left" in d){c.x=parseInt(d.left);c.y=parseInt(d.right)}else{if("x" in d){c.x=parseInt(d.x);c.y=parseInt(d.y)}}return c};a.TObjectPainter.prototype.FinishTextDrawing=function(l,i){if(!l){l=this.draw_g}var d=this;var k=null;if(l.property("mathjax_use")){l.property("mathjax_use",false);var g=false;k=l.selectAll(".math_svg");k.each(function(){var m=b.select(this);if(m.node().parentNode!==l.node()){return}var f=m.property("_element");if(b.select(f).select("svg").empty()){g=true}});if(g){a.AssertPrerequisites("mathjax",function(){if(typeof MathJax=="object"){MathJax.Hub.Queue(["FinishTextDrawing",d,l,i])}});return null}}if(k==null){k=l.selectAll(".math_svg")}var j=this,c=0;var h=l.property("text_factor");if((h>0)&&((h<0.9)||(h>1))){var e=l.property("text_font");e.size=Math.floor(e.size/h);if(l.property("max_font_size")&&(e.size>l.property("max_font_size"))){e.size=l.property("max_font_size")}l.call(e.func)}k.each(function(){var o=b.select(this);if(o.node().parentNode!==l.node()){return}var n=o.property("_element"),f=o.property("_rotate");o.property("_element",null);var p=b.select(n).select("svg");if(p.empty()){a.console("MathJax SVG ouptut error");return}p.remove();document.body.removeChild(n);o.append(function(){return p.node()});if(o.property("_scale")){var m=j.GetBoundarySizes(o.node());c=Math.max(c,1.05*m.width/o.property("_width"),1.05*m.height/o.property("_height"))}});k.each(function(){var z=b.select(this);if(z.node().parentNode!==l.node()){return}if(c>0){var n=z.select("svg");var w=n.attr("width"),t=n.attr("height");if((typeof w=="string")&&(typeof t=="string")&&(w.indexOf("ex")>0)&&(t.indexOf("ex")>0)){w=parseFloat(w.substr(0,w.length-2));t=parseFloat(t.substr(0,t.length-2));if((w>0)&&(t>0)){n.attr("width",(w/c).toFixed(2)+"ex");n.attr("height",(t/c).toFixed(2)+"ex")}}else{a.console("Fail to downscale MathJax output")}}var r=j.GetBoundarySizes(z.node()),u=z.property("_align"),p=z.property("_rotate"),o=z.property("_width"),x=z.property("_height"),v={x:z.property("_x"),y:z.property("_y")};var f={x:1,y:1},s="x",q="y";if(p==180){f.x=f.y=-1}else{if((p==270)||(p==90)){f.x=(p===270)?-1:1;f.y=-f.x;s="y";q="x"}}if(!z.property("_scale")){o=x=0}if(u[0]=="middle"){v[s]+=f.x*(o-r.width)/2}else{if(u[0]=="end"){v[s]+=f.x*(o-r.width)}}if(u[1]=="middle"){v[q]+=f.y*(x-r.height)/2}else{if(u[1]=="bottom"){v[q]+=f.y*(x-r.height)}}var y="translate("+v.x+","+v.y+")";if(p!==0){y+=" rotate("+p+",0,0)"}z.attr("transform",y).attr("visibility",null)});l.selectAll(".hidden_text").attr("opacity","1").classed("hidden_text",false);a.CallBack(i);return l.property("max_text_width")};a.TObjectPainter.prototype.DrawText=function(q,m,k,n,v,i,z,o,A){if(!A){A=this.draw_g}var s;if(typeof q=="string"){s=q.split(";");if(s.length==1){s.push("middle")}}else{s=["start","middle"];if((q/10)>=3){s[0]="end"}else{if((q/10)>=2){s[0]="middle"}}if((q%10)==0){s[1]="bottom"}else{if((q%10)==1){s[1]="bottom"}else{if((q%10)==3){s[1]="top"}}}}var B=(n>0)&&(v>0);if(o==null){o=1}if(o<2){if(!a.Painter.isAnyLatex(i)){o=0}}var u=((a.gStyle.MathJax<1)&&(o!==2))||(o<1);if(u){if(o>0){i=a.Painter.translateLaTeX(i)}var d=m.toFixed(1),c=k.toFixed(1),j=null,f=false;if(n>0){if(s[0]=="middle"){d=(m+n*0.5).toFixed(1)}else{if(s[0]=="end"){d=(m+n).toFixed(1)}}}if(v>0){if(s[1]=="bottom"){c=(k+v).toFixed(1)}else{if(s[1]=="top"){j=".8em"}else{c=(k+v/2).toFixed(1);if(a.browser.isIE){j=".4em"}else{f=true}}}}else{if(s[1]=="top"){j=".8em"}else{if(s[1]=="middle"){if(a.browser.isIE){j=".4em"}else{f=true}}}}var g="translate("+d+","+c+")";if(!B&&(v<0)){g+=" rotate("+(-v)+",0,0)"}var p=A.append("text").attr("text-anchor",s[0]).attr("x",0).attr("y",0).attr("fill",z?z:null).attr("transform",g).text(i);if(j!=null){p.attr("dy",j)}if(f){p.attr("dominant-baseline","middle")}var l=this.GetBoundarySizes(p.node());if(B){p.classed("hidden_text",true).attr("opacity","0")}if(l.width>A.property("max_text_width")){A.property("max_text_width",l.width)}if((n>0)&&B){this.TextScaleFactor(1.05*l.width/n,A)}if((v>0)&&B){this.TextScaleFactor(1*l.height/v,A)}return l.width}n=Math.round(n);v=Math.round(v);m=Math.round(m);k=Math.round(k);var t=0;if(!B&&v<0){t=Math.abs(v);v=0}var r=A.append("svg:g").attr("class","math_svg").attr("visibility","hidden").property("_x",m).property("_y",k).property("_width",n).property("_height",v).property("_scale",B).property("_rotate",t).property("_align",s);var e=document.createElement("div");b.select(e).style("visibility","hidden").style("overflow","hidden").style("position","absolute").html(a.Painter.translateMath(i,o,z));document.body.appendChild(e);A.property("mathjax_use",true);r.property("_element",e);a.AssertPrerequisites("mathjax",function(){if(typeof MathJax=="object"){MathJax.Hub.Queue(["Typeset",MathJax.Hub,e])}});return 0};a.TFramePainter=function(c){a.TObjectPainter.call(this,c);this.tooltip_enabled=true;this.tooltip_allowed=(a.gStyle.Tooltip>0)};a.TFramePainter.prototype=Object.create(a.TObjectPainter.prototype);a.TFramePainter.prototype.Shrink=function(d,c){this.fX1NDC+=d;this.fX2NDC-=c};a.TFramePainter.prototype.UpdateAttributes=function(d){var e=this.root_pad(),c=this.GetObject();if((this.fX1NDC===undefined)||(d&&!this.modified_NDC)){if(!e){a.extend(this,a.gStyle.FrameNDC)}else{a.extend(this,{fX1NDC:e.fLeftMargin,fX2NDC:1-e.fRightMargin,fY1NDC:e.fBottomMargin,fY2NDC:1-e.fTopMargin})}}if(this.fillatt===undefined){if(c){this.fillatt=this.createAttFill(c)}else{if(e){this.fillatt=this.createAttFill(null,e.fFrameFillStyle,e.fFrameFillColor)}else{this.fillatt=this.createAttFill(null,1001,0)}}if(this.fillatt.color=="none"){this.fillatt.color="white"}}if(this.lineatt===undefined){this.lineatt=a.Painter.createAttLine(c?c:"black")}};a.TFramePainter.prototype.Redraw=function(){this.UpdateAttributes();var d=this.pad_width(),r=this.pad_height(),k=Math.round(d*this.fX1NDC),p=Math.round(d*(this.fX2NDC-this.fX1NDC)),q=Math.round(r*(1-this.fY2NDC)),j=Math.round(r*(this.fY2NDC-this.fY1NDC));this.draw_g=this.svg_frame();if(this.draw_g.empty()){return console.error("did not found frame layer")}var e=this.draw_g.select("rect"),f=this.draw_g.select(".main_layer");if(f.empty()){this.draw_g.append("svg:title").text("");e=this.draw_g.append("svg:rect");this.draw_g.append("svg:g").attr("class","grid_layer");f=this.draw_g.append("svg:svg").attr("class","main_layer").attr("x",0).attr("y",0).attr("overflow","hidden");this.draw_g.append("svg:g").attr("class","axis_layer");this.draw_g.append("svg:g").attr("class","upper_layer")}this.draw_g.property("frame_painter",this);this.draw_g.attr("x",k).attr("y",q).attr("width",p).attr("height",j).property("draw_x",k).property("draw_y",q).property("draw_width",p).property("draw_height",j).attr("transform","translate("+k+","+q+")");e.attr("x",0).attr("y",0).attr("width",p).attr("height",j).call(this.fillatt.func).call(this.lineatt.func);f.attr("width",p).attr("height",j).attr("viewBox","0 0 "+p+" "+j);this.AddDrag({obj:this,only_resize:true,minwidth:20,minheight:20,redraw:this.RedrawPad.bind(this)});var c=this.draw_g.select(".interactive_rect");if(a.gStyle.Tooltip===0){return c.remove()}var m=this;function o(){var h=b.mouse(c.node());m.ProcessTooltipEvent({x:h[0],y:h[1],touch:false})}function g(){m.ProcessTooltipEvent(null)}function i(){var h=b.touches(c.node());if(!h||h.length!==1){return m.ProcessTooltipEvent(null)}m.ProcessTooltipEvent({x:h[0][0],y:h[0][1],touch:true})}function l(){m.ProcessTooltipEvent(null)}if(c.empty()){c=this.draw_g.append("rect").attr("class","interactive_rect").style("opacity","0").style("fill","none").style("pointer-events","visibleFill").on("mouseenter",o).on("mousemove",o).on("mouseleave",g);if(a.touches){c.on("touchstart",i).on("touchmove",i).on("touchend",l).on("touchcancel",l)}}c.attr("x",0).attr("y",0).attr("width",p).attr("height",j);var n=this.svg_layer("stat_layer").select(".objects_hints");if(!n.empty()&&(a.gStyle.Tooltip>0)){setTimeout(this.ProcessTooltipEvent.bind(this,n.property("last_point")),10)}};a.TFramePainter.prototype.FillContextMenu=function(f){var c=this.main_painter(),e=f.size()==0,d=this.root_pad();if(e){f.add("header:Frame")}else{f.add("separator")}if(c){if(c.zoom_xmin!==c.zoom_xmax){f.add("Unzoom X",c.Unzoom.bind(c,"x"))}if(c.zoom_ymin!==c.zoom_ymax){f.add("Unzoom Y",c.Unzoom.bind(c,"y"))}if(c.zoom_zmin!==c.zoom_zmax){f.add("Unzoom Z",c.Unzoom.bind(c,"z"))}f.add("Unzoom all",c.Unzoom.bind(c,"xyz"));if(d){f.addchk(d.fLogx,"SetLogx",c.ToggleLog.bind(c,"x"));f.addchk(d.fLogy,"SetLogy",c.ToggleLog.bind(c,"y"));if(c.Dimension()==2){f.addchk(d.fLogz,"SetLogz",c.ToggleLog.bind(c,"z"))}}f.add("separator")}f.addchk(this.tooltip_allowed,"Show tooltips",function(){var g=this.frame_painter();if(g){g.tooltip_allowed=!g.tooltip_allowed}});this.FillAttContextMenu(f,e?"":"Frame ");f.add("separator");f.add("Save as frame.png",function(g){var h=this.svg_frame();if(!h.empty()){a.AssertPrerequisites("savepng",function(){saveSvgAsPng(h.node(),"frame.png")})}});return true};a.TFramePainter.prototype.IsTooltipShown=function(){if(a.gStyle.Tooltip<1){return false}return !(this.svg_layer("stat_layer").select(".objects_hints").empty())};a.TFramePainter.prototype.ProcessTooltipEvent=function(R,o){if(o!==undefined){this.tooltip_enabled=o}if((R===undefined)||!this.tooltip_allowed||!this.tooltip_enabled){R=null}var L=[],F=0,w=0,D=0,E=false,O=11,A=3,B=3,j=1.2,e=this.frame_height(),c=this.frame_width(),t=this.pad_painter(true),C=this.pad_height()-this.draw_g.property("draw_y"),Q=a.Painter.getFontDetails(160,O);if(t!==null){L=t.GetTooltips(R)}if(R&&R.touch){O=15}for(var M=0;M1){var u=0.5,x=0.5;if(q=="left"){x=0.7}else{if(q=="right"){u=0.3}}if(R.x<=u*c){q="left";v=20}else{if(R.x>=x*c){q="right";v=c-60}else{v=f.property("startx")}}}else{q="single"}if(q!==f.property("viewmode")){f.property("viewmode",q);f.selectAll("*").remove()}var s=10,p=10,g=-1111,J=-1111;function d(S){for(var r=0;(r=S-5)&&(l.y<=S+l.height+5)){S=l.y+10;r=-1}}return S}for(var M=0;M1){var k=E?z.color1:z.color2;if((k!==undefined)&&(k!=="none")){K.attr("stroke",k).attr("stroke-width",z.exact?3:1)}}if(z.lines!=null){for(var N=0;Nc-20)){v=c-P-20;I.attr("x",v)}if((q!=="single")&&(p=v-5)){I.attr("y",function(){return b.select(this).property("gapy")})}}if(P>10){I.attr("width",P).select("rect").attr("width",P)}f.property("startx",v)};a.Painter.drawFrame=function(e,d){var c=new a.TFramePainter(d);c.SetDivId(e,2);c.Redraw();return c.DrawingReady()};a.TPavePainter=function(c){a.TObjectPainter.call(this,c);this.Enabled=true;this.UseContextMenu=true;this.UseTextColor=false};a.TPavePainter.prototype=Object.create(a.TObjectPainter.prototype);a.TPavePainter.prototype.DrawPave=function(d){this.UseTextColor=false;if(!this.Enabled){return this.RemoveDrawG()}var i=this.GetObject();if(i.fInit===0){i.fInit=1;var h=this.root_pad();if(i.fOption.indexOf("NDC")>=0){i.fX1NDC=i.fX1;i.fX2NDC=i.fX2;i.fY1NDC=i.fY1;i.fY2NDC=i.fY2}else{if(h!==null){if(h.fLogx){if(i.fX1>0){i.fX1=a.log10(i.fX1)}if(i.fX2>0){i.fX2=a.log10(i.fX2)}}if(h.fLogy){if(i.fY1>0){i.fY1=a.log10(i.fY1)}if(i.fY2>0){i.fY2=a.log10(i.fY2)}}i.fX1NDC=(i.fX1-h.fX1)/(h.fX2-h.fX1);i.fY1NDC=(i.fY1-h.fY1)/(h.fY2-h.fY1);i.fX2NDC=(i.fX2-h.fX1)/(h.fX2-h.fX1);i.fY2NDC=(i.fY2-h.fY1)/(h.fY2-h.fY1)}else{i.fX1NDC=i.fY1NDC=0.1;i.fX2NDC=i.fY2NDC=0.9}}}var f=Math.round(i.fX1NDC*this.pad_width()),e=Math.round((1-i.fY2NDC)*this.pad_height()),g=Math.round((i.fX2NDC-i.fX1NDC)*this.pad_width()),c=Math.round((i.fY2NDC-i.fY1NDC)*this.pad_height()),j=i.fBorderSize;this.RecreateDrawG(true,this.IsStats()?"stat_layer":"text_layer");this.draw_g.attr("x",f).attr("y",e).attr("width",g).attr("height",c).attr("transform","translate("+f+","+e+")");if((j>1)&&(i.fShadowColor>0)){this.draw_g.append("svg:path").attr("d","M"+g+","+c+" v"+(-c+j)+" h"+j+" v"+c+" h"+(-g)+" v"+(-j)+" Z").style("fill",a.Painter.root_colors[i.fShadowColor]).style("stroke",a.Painter.root_colors[i.fShadowColor]).style("stroke-width","1px")}if(this.lineatt===undefined){this.lineatt=a.Painter.createAttLine(i,j>0?1:0)}if(this.fillatt===undefined){this.fillatt=this.createAttFill(i)}this.draw_g.append("rect").attr("x",0).attr("y",0).attr("width",g).attr("height",c).style("pointer-events","visibleFill").call(this.fillatt.func).call(this.lineatt.func);if("PaveDrawFunc" in this){this.PaveDrawFunc(g,c,d)}this.AddDrag({obj:i,minwidth:10,minheight:20,redraw:this.DrawPave.bind(this),ctxmenu:a.touches&&a.gStyle.ContextMenu&&this.UseContextMenu});if(this.UseContextMenu&&a.gStyle.ContextMenu){this.draw_g.on("contextmenu",this.ShowContextMenu.bind(this))}};a.TPavePainter.prototype.DrawPaveLabel=function(e,c){this.UseTextColor=true;var d=this.GetObject();this.StartTextDrawing(d.fTextFont,c/1.2);this.DrawText(d.fTextAlign,0,0,e,c,d.fLabel,a.Painter.root_colors[d.fTextColor]);this.FinishTextDrawing()};a.TPavePainter.prototype.DrawPaveText=function(A,q,e){if(e&&this.IsStats()){this.FillStatistic()}var u=this.GetObject(),J=a.Painter.root_colors[u.fTextColor],H=u.fBorderSize,I=0,F=0,p=u.fLines.arr.length,d=[],G=0;for(var D=0;D0){G=Math.max(G,o.length)}if(!this.IsStats()||(D==0)||(o.indexOf("|")<0)){continue}if(I===0){I=D}var z=o.split("|");if(z.length>F){F=z.length}}var v=q/p,g=false,K=u.fMargin*A;this.StartTextDrawing(u.fTextFont,q/(p*1.2));if(p==1){this.DrawText(u.fTextAlign,0,0,A,q,d[0],J);this.UseTextColor=true}else{for(var D=0;D0)&&(D>=I)){var z=d[D].split("|");for(var s=0;s0)&&g){this.draw_g.append("svg:line").attr("x1",0).attr("y1",v.toFixed(1)).attr("x2",A).attr("y2",v.toFixed(1)).call(this.lineatt.func)}if((I>0)&&(F>1)){for(var B=I;B0)&&!this.IsStats()){var l=Math.round(A*0.25),i=Math.round(-q*0.02),m=Math.round(A*0.5),E=Math.round(q*0.04);var f=this.draw_g.append("svg:g");f.append("rect").attr("x",l).attr("y",i).attr("width",m).attr("height",E).call(this.fillatt.func).call(this.lineatt.func);this.StartTextDrawing(u.fTextFont,E/1.5,f);this.DrawText(22,l,i,m,E,u.fLabel,J,1,f);this.FinishTextDrawing(f);this.UseTextColor=true}};a.TPavePainter.prototype.Format=function(f,c){if(!c){c="stat"}var e=this.GetObject();if(c=="stat"){c=e.fStatFormat;if(!c){c=a.gStyle.StatFormat}}else{if(c=="fit"){c=e.fFitFormat;if(!c){c=a.gStyle.FitFormat}}else{if(c=="entries"){if(f<1000000000){return f.toFixed(0)}c="14.7g"}else{if(c=="last"){c=this.lastformat}}}}delete this.lastformat;if(!c){c="6.4g"}var d=a.FFormat(f,c);this.lastformat=a.lastFFormat;return d};a.TPavePainter.prototype.ShowContextMenu=function(e){if(!e){b.event.stopPropagation();b.event.preventDefault();e=b.event}var c=this,d=this.GetObject();a.Painter.createMenu(function(g){g.painter=c;g.add("header: "+d._typename+"::"+d.fName);if(c.IsStats()){g.add("SetStatFormat",function(){var h=prompt("Enter StatFormat",d.fStatFormat);if(h!=null){d.fStatFormat=h;c.Redraw()}});g.add("SetFitFormat",function(){var h=prompt("Enter FitFormat",d.fFitFormat);if(h!=null){d.fFitFormat=h;c.Redraw()}});g.add("separator");g.add("sub:SetOptStat",function(){var h=prompt("Enter OptStat",d.fOptStat);if(h!=null){d.fOptStat=parseInt(h);c.Redraw()}});function f(j,h){var i=(j<10)?d.fOptStat:d.fOptFit;i=parseInt(parseInt(i)/parseInt(Math.pow(10,j%10)))%10;g.addchk(i,h,i*100+j,function(k){var m=(k%100<10)?d.fOptStat:d.fOptFit;var l=parseInt(k/100);m-=(l>0?l:-1)*parseInt(Math.pow(10,k%10));if(k%100<10){d.fOptStat=m}else{d.fOptFit=m}c.Redraw()})}f(0,"Histogram name");f(1,"Entries");f(2,"Mean");f(3,"Std Dev");f(4,"Underflow");f(5,"Overflow");f(6,"Integral");f(7,"Skewness");f(8,"Kurtosis");g.add("endsub:");g.add("sub:SetOptFit",function(){var h=prompt("Enter OptStat",d.fOptFit);if(h!=null){d.fOptFit=parseInt(h);c.Redraw()}});f(10,"Fit parameters");f(11,"Par errors");f(12,"Chi square / NDF");f(13,"Probability");g.add("endsub:");g.add("separator")}if(c.UseTextColor){c.TextAttContextMenu(g)}c.FillAttContextMenu(g);g.show(e)})};a.TPavePainter.prototype.IsStats=function(){return this.MatchObjectType("TPaveStats")};a.TPavePainter.prototype.FillStatistic=function(){var e=this.GetObject(),c=this.main_painter();if(e.fName!=="stats"){return false}if((c===null)||!("FillStatistic" in c)){return false}if(c.IsDummyHisto()){return true}var d=new Number(e.fOptStat);var f=new Number(e.fOptFit);if(!d){d=a.gStyle.OptStat}if(!f){f=a.gStyle.OptFit}e.Clear();c.FillStatistic(this,d,f);return true};a.TPavePainter.prototype.UpdateObject=function(d){if(!this.MatchObjectType(d)){return false}var c=this.GetObject();if(!("modified_NDC" in c)){c.fInit=d.fInit;c.fX1=d.fX1;c.fX2=d.fX2;c.fY1=d.fY1;c.fY2=d.fY2;c.fX1NDC=d.fX1NDC;c.fX2NDC=d.fX2NDC;c.fY1NDC=d.fY1NDC;c.fY2NDC=d.fY2NDC}if(d._typename==="TPaveText"){c.fLines=a.clone(d.fLines);return true}else{if(d._typename==="TPaveLabel"){c.fLabel=d.fLabel;return true}else{if(d._typename==="TPaveStats"){c.fOptStat=d.fOptStat;c.fOptFit=d.fOptFit;return true}}}return false};a.TPavePainter.prototype.Redraw=function(){this.DrawPave(true)};a.Painter.drawPaveText=function(g,f,e){var d=((typeof e=="string")&&(e.indexOf("onpad:")==0))?e.substr(6):undefined;var c=new a.TPavePainter(f);c.SetDivId(g,2,d);switch(f._typename){case"TPaveLabel":c.PaveDrawFunc=c.DrawPaveLabel;break;case"TPaveStats":case"TPaveText":c.PaveDrawFunc=c.DrawPaveText;break}c.Redraw();return c.DrawingReady()};a.TPadPainter=function(d,c){a.TObjectPainter.call(this,d);this.pad=d;this.iscan=c;this.this_pad_name="";if(!this.iscan&&(d!==null)&&("fName" in d)){this.this_pad_name=d.fName.replace(" ","_")}this.painters=new Array;this.has_canvas=true};a.TPadPainter.prototype=Object.create(a.TObjectPainter.prototype);a.TPadPainter.prototype.ButtonSize=function(c){return Math.round((!c?1:c)*(this.iscan||!this.has_canvas?16:12))};a.TPadPainter.prototype.CreateCanvasSvg=function(f,d){var e=this.select_main();var l=this.main_visible_rect();var m=l.width,g=l.height;if((typeof d=="object")&&(d!==null)&&("width" in d)&&("height" in d)){m=d.width;g=d.height}var k=null,i=null;if(f>0){i=this.svg_canvas();var j=i.property("draw_width"),c=i.property("draw_height");if((m<=0)&&(g<=0)){i.attr("visibility","hidden");return false}else{i.attr("visibility","visible");i.select(".canvas_fillrect").call(this.fillatt.func)}if(f==1){if((j==m)&&(c==g)){return false}}k=i.property("height_factor");if(k!=null){g=Math.round(m*k);e.style("height",g+"px")}if((f==1)&&(j>0)&&(c>0)&&!i.property("redraw_by_resize")){if((m/j>0.66)&&(m/j<1.5)&&(g/c>0.66)&&(g/c<1.5)){return false}}}else{if((g<10)&&(m>0)){k=0.66;if((this.pad!==null)&&("fCw" in this.pad)&&("fCh" in this.pad)&&(this.pad.fCw>0)){k=this.pad.fCh/this.pad.fCw;if((k<0.1)||(k>10)){k=0.66}}g=Math.round(m*k);e.style("height",g+"px")}i=this.select_main().append("svg").attr("class","jsroot root_canvas").property("pad_painter",this).property("mainpainter",null).property("current_pad","").property("redraw_by_resize",false);i.append("svg:title").text("ROOT canvas");i.append("svg:rect").attr("class","canvas_fillrect").attr("x",0).attr("y",0).style("pointer-events","visibleFill");i.append("svg:g").attr("class","root_frame");i.append("svg:g").attr("class","subpads_layer");i.append("svg:g").attr("class","special_layer");i.append("svg:g").attr("class","text_layer");i.append("svg:g").attr("class","stat_layer");i.append("svg:g").attr("class","btns_layer");if(a.gStyle.ContextMenu){i.select(".canvas_fillrect").on("contextmenu",this.ShowContextMenu.bind(this))}}if(!this.fillatt||!this.fillatt.changed){this.fillatt=this.createAttFill(this.pad,1001,0)}if((m<=0)||(g<=0)){i.attr("visibility","hidden");m=200;g=100}else{i.attr("visibility","visible")}i.attr("x",0).attr("y",0).attr("width","100%").attr("height","100%").attr("viewBox","0 0 "+m+" "+g).attr("preserveAspectRatio","none").property("height_factor",k).property("draw_x",0).property("draw_y",0).property("draw_width",m).property("draw_height",g);i.select(".canvas_fillrect").attr("width",m).attr("height",g).call(this.fillatt.func);this.svg_layer("btns_layer").attr("transform","translate(2,"+(g-this.ButtonSize(1.25))+")");return true};a.TPadPainter.prototype.CreatePadSvg=function(m){if(!this.has_canvas){return this.CreateCanvasSvg(m?2:0)}var c=this.svg_canvas().property("draw_width"),l=this.svg_canvas().property("draw_height"),k=Math.round(this.pad.fAbsWNDC*c),g=Math.round(this.pad.fAbsHNDC*l),j=Math.round(this.pad.fAbsXlowNDC*c),i=Math.round(l-this.pad.fAbsYlowNDC*l)-g;var d=null,f=null,e=null;if(m){d=this.svg_pad(this.this_pad_name);f=d.select(".root_pad_border");e=this.svg_layer("btns_layer",this.this_pad_name)}else{d=this.svg_canvas().select(".subpads_layer").append("g").attr("class","root_pad").attr("pad",this.this_pad_name).property("pad_painter",this).property("mainpainter",null);f=d.append("svg:rect").attr("class","root_pad_border");d.append("svg:g").attr("class","root_frame");d.append("svg:g").attr("class","special_layer");d.append("svg:g").attr("class","text_layer");d.append("svg:g").attr("class","stat_layer");e=d.append("svg:g").attr("class","btns_layer").property("nextx",0);if(a.gStyle.ContextMenu){d.select(".root_pad_border").on("contextmenu",this.ShowContextMenu.bind(this))}if(!this.fillatt||!this.fillatt.changed){this.fillatt=this.createAttFill(this.pad,1001,0)}if(!this.lineatt||!this.lineatt.changed){this.lineatt=a.Painter.createAttLine(this.pad)}if(this.pad.fBorderMode==0){this.lineatt.color="none"}}d.attr("transform","translate("+j+","+i+")").property("draw_x",j).property("draw_y",i).property("draw_width",k).property("draw_height",g);f.attr("x",0).attr("y",0).attr("width",k).attr("height",g).call(this.fillatt.func).call(this.lineatt.func);e.attr("transform","translate("+(k-e.property("nextx")-this.ButtonSize(0.25))+","+(g-this.ButtonSize(1.25))+")")};a.TPadPainter.prototype.CheckColors=function(d){if(d==null){return}for(var c=0;c=0){this.pad.fPrimitives.RemoveAt(c)}};a.TPadPainter.prototype.FindPrimitive=function(g,f,c){if((this.pad===null)||(this.pad.fPrimitives===null)){return null}for(var d=0;d=this.pad.fPrimitives.arr.length)){return a.CallBack(e)}var c=a.draw(this.divid,this.pad.fPrimitives.arr[d],this.pad.fPrimitives.opt[d]);if(c===null){return this.DrawPrimitive(d+1,e)}c._primitive=true;c.WhenReady(this.DrawPrimitive.bind(this,d+1,e))};a.TPadPainter.prototype.GetTooltips=function(e){var c=[],d=[];if(this.painters!==null){this.painters.forEach(function(f){if("ProcessTooltip" in f){c.push(f)}})}if(e){e.nproc=c.length}c.forEach(function(f){var g=f.ProcessTooltip(e);d.push(g);if(g&&e.painters){g.painter=f}});return d};a.TPadPainter.prototype.FillContextMenu=function(d){if(this.pad){d.add("header: "+this.pad._typename+"::"+this.pad.fName)}else{d.add("header: Canvas")}if(this.iscan){d.addchk((a.gStyle.Tooltip>0),"Show tooltips",function(){a.gStyle.Tooltip=(a.gStyle.Tooltip===0)?1:-a.gStyle.Tooltip})}if(!this._websocket){function c(g){this.pad[g]=this.pad[g]?0:1;var f=this.svg_pad(this.this_pad_name).property("mainpainter");if(!f){return}if((g.indexOf("fGrid")==0)&&(typeof f.DrawGrids=="function")){return f.DrawGrids()}if((g.indexOf("fTick")==0)&&(typeof f.DrawAxes=="function")){return f.DrawAxes()}}d.addchk(this.pad.fGridx,"Grid x","fGridx",c);d.addchk(this.pad.fGridy,"Grid y","fGridy",c);d.addchk(this.pad.fTickx,"Tick x","fTickx",c);d.addchk(this.pad.fTicky,"Tick y","fTicky",c);this.FillAttContextMenu(d)}d.add("separator");var e="canvas.png";if(!this.iscan){e=this.this_pad_name+".png"}d.add("Save as "+e,e,function(f){var g=this.svg_pad(this.this_pad_name);if(!g.empty()){a.AssertPrerequisites("savepng",function(){console.log("create",f);g.selectAll(".btns_layer").style("display","none");saveSvgAsPng(g.node(),f);g.selectAll(".btns_layer").style("display","")})}});return true};a.TPadPainter.prototype.ShowContextMenu=function(e){if(!e){var d=b.mouse(this.svg_pad(this.this_pad_name).node());if(d&&(d.length==2)&&(d[0]>0)&&(d[0]<10)&&(d[1]>0)&&d[1]<10){return}b.event.stopPropagation();b.event.preventDefault();e=b.event}var c=this;a.Painter.createMenu(function(f){f.painter=c;c.FillContextMenu(f);c.FillObjectExecMenu(f,function(){f.show(e)})})};a.TPadPainter.prototype.Redraw=function(c){if(this.iscan){this.CreateCanvasSvg(2)}else{this.CreatePadSvg(true)}for(var d=0;d0)){r.add("separator");var p=[];for(var s=0;s=0)){continue}var o=("_typename" in q)?(q._typename+"::"):"";if("fName" in q){o+=q.fName}if(o.length==0){o="item"+s}r.add(o,s,d.ItemContextMenu)}}r.show(n)});return}var j=false;for(var k=0;k=0)){f.fFillColor=0}d.SetDivId(g,-1);d.CheckColors(f);d.CreateCanvasSvg(0);d.SetDivId(g);d.AddButton(a.ToolbarIcons.camera,"Create PNG","CanvasSnapShot");if(a.gStyle.ContextMenu){d.AddButton(a.ToolbarIcons.question,"Access context menus","PadContextMenus")}if(c&&e.indexOf("noframe")<0){a.Painter.drawFrame(g,null)}d.DrawPrimitive(0,function(){d.DrawingReady()});return d};a.Painter.drawPad=function(g,f,d){var c=new a.TPadPainter(f,false);if(f&&d&&(d.indexOf("white")>=0)){f.fFillColor=0}c.SetDivId(g);if(c.svg_canvas().empty()){c.has_canvas=false;c.this_pad_name=""}c.CreatePadSvg();if(c.MatchObjectType("TPad")&&(!c.has_canvas||c.HasObjectsToDraw())){c.AddButton(a.ToolbarIcons.camera,"Create PNG","PadSnapShot");if(a.gStyle.ContextMenu){c.AddButton(a.ToolbarIcons.question,"Access context menus","PadContextMenus")}}var e;if(c.has_canvas){e=c.CurrentPadName(c.this_pad_name)}c.DrawPrimitive(0,function(){c.CurrentPadName(e);c.DrawingReady()});return c};a.TAxisPainter=function(d,c){a.TObjectPainter.call(this,d);this.embedded=c;this.name="yaxis";this.kind="normal";this.func=null;this.order=0;this.full_min=0;this.full_max=1;this.scale_min=0;this.scale_max=1;this.ticks=[]};a.TAxisPainter.prototype=Object.create(a.TObjectPainter.prototype);a.TAxisPainter.prototype.SetAxisConfig=function(e,g,h,f,d,c,i){this.name=e;this.kind=g;this.func=h;this.full_min=f;this.full_max=d;this.scale_min=c;this.scale_max=i};a.TAxisPainter.prototype.CreateFormatFuncs=function(){var e=this.GetObject(),d=(e&&e._typename==="TGaxis");delete this.format;var i=508;if(e!==null){i=Math.max(d?e.fNdiv:e.fNdivisions,4)}this.nticks=i%100;this.nticks2=(i%10000-this.nticks)/100;this.nticks3=Math.floor(i/10000);if(e&&!d&&(this.nticks>7)){this.nticks=7}var f=Math.abs(this.func.range()[1]-this.func.range()[0]);if(f<=0){f=100}if(this.kind=="time"){if(this.nticks>8){this.nticks=8}var c=this.scale_max-this.scale_min;var h=a.Painter.getTimeFormat(e);if((h.length==0)||(c<0.1*(this.full_max-this.full_min))){h=a.Painter.chooseTimeFormat(c/this.nticks,true)}var g=a.Painter.chooseTimeFormat(c/f,false);this.tfunc1=this.tfunc2=b.time.format(h);if(g!==h){this.tfunc2=b.time.format(g)}this.format=function(k,j){return j?this.tfunc1(k):this.tfunc2(k)}}else{if(this.kind=="log"){this.nticks2=1;this.noexp=e?e.TestBit(a.EAxisBits.kNoExponent):false;if((this.scale_max<300)&&(this.scale_min>0.3)){this.noexp=true}this.moreloglabels=e?e.TestBit(a.EAxisBits.kMoreLogLabels):false;this.format=function(o,j,m){var n=parseFloat(o);if(!j){var l=Math.round(n);return((l===n)&&(Math.abs(l)<1000000000))?l.toString():n.toExponential(4)}if(n<=0){return null}var k=a.log10(n);if(this.moreloglabels||(Math.abs(k-Math.round(k))<0.001)){if(!this.noexp&&!m){return a.Painter.formatExp(n.toExponential(0))}else{if(k<0){return n.toFixed(Math.round(-k+0.5))}else{return n.toFixed(0)}}}return null}}else{if(this.kind=="labels"){this.nticks=50;var c=this.scale_max-this.scale_min;if(this.nticks>c){this.nticks=Math.round(c)}this.nticks2=1;this.axis=e;this.format=function(m){var l=Math.round(parseInt(m))+1;if((l<1)||(l>this.axis.fNbins)){return null}for(var k=0;k0?this.ndig:0);if((typeof m=="string")&&(m.length<=l.length+1)){return m}return l}l=l/Math.pow(10,this.order);k=Math.round(l);if(l===k){return k.toString()}return l.toFixed(this.ndig+this.order>0?this.ndig+this.order:0)}if(l===k){return(Math.abs(k)<1000000000)?k.toString():l.toExponential(4)}return l.toFixed(this.ndig+2>0?this.ndig+2:0)}}}}};a.TAxisPainter.prototype.CreateTicks=function(){var d={nminor:0,nmiddle:0,nmajor:0,func:this.func};d.minor=d.middle=d.major=this.func.ticks(this.nticks);if(this.nticks2>1){d.minor=d.middle=this.func.ticks(d.major.length*this.nticks2);var c=Math.abs(this.func.range()[1]-this.func.range()[0]);if((d.middle.length<=d.major.length)||(d.middle.length>c/3.5)){d.minor=d.middle=d.major}else{if((this.nticks3>1)&&(this.kind!=="log")){d.minor=this.func.ticks(d.middle.length*this.nticks3);if((d.minor.length<=d.middle.length)||(d.minor.length>c/1.7)){d.minor=d.middle}}}}d.reset=function(){this.nminor=this.nmiddle=this.nmajor=0};d.next=function(e){if(this.nminor>=this.minor.length){return false}this.tick=this.minor[this.nminor++];this.grpos=this.func(this.tick);if(e){this.grpos=Math.round(this.grpos)}this.kind=3;if((this.nmiddle=this.major.length){return null}return this.func(this.major[this.nmajor])};return d};a.TAxisPainter.prototype.IsCenterLabels=function(){if(this.kind==="labels"){return true}if(this.kind==="log"){return false}var c=this.GetObject();return c&&c.TestBit(a.EAxisBits.kCenterLabels)};a.TAxisPainter.prototype.DrawAxis=function(D,j,S,ab,K,W,s){var E=this.GetObject(),Y=(E&&E._typename==="TGaxis"),v=(this.name==="zaxis")?-1:1,ac=0,ae=j,m=10,n=100,o=100;this.vertical=D;if(!s){s=0}if(Y){if(!this.lineatt){this.lineatt=a.Painter.createAttLine(E)}n=(D?this.pad_width():this.pad_height());o=Math.min(this.pad_width(),this.pad_height());m=Math.round(E.fTickSize*n)}else{if(!this.lineatt){this.lineatt=a.Painter.createAttLine(E.fAxisColor,1)}n=(D?S:ab);m=Math.round(E.fTickLength*n);o=Math.min(S,ab)}if(!Y||(this.name==="zaxis")){ae=j.select("."+this.name+"_container");if(ae.empty()){ae=j.append("svg:g").attr("class",this.name+"_container")}else{ae.selectAll("*").remove()}}else{if((E.fChopt.indexOf("-")>=0)&&(E.fChopt.indexOf("+")<0)){v=-1}else{if(D&&E.fChopt=="+L"){v=-1}else{if((E.fChopt.indexOf("-")>=0)&&(E.fChopt.indexOf("+")>=0)){v=1;ac=1}}}ae.append("svg:line").attr("x1",0).attr("y1",0).attr("x1",D?0:S).attr("y1",D?ab:0).call(this.lineatt.func)}if(K!==undefined){ae.attr("transform",K)}this.CreateFormatFuncs();var U=this.IsCenterLabels(),P="",e="",g=0,ag=0,k=1;this.ticks=[];var z=this.CreateTicks();while(z.next(true)){var J=Math.round(m/4),H=0;if(z.kind<3){J=Math.round(m/2)}if(z.kind==1){if(!("format" in this)||(this.format(z.tick,true)!==null)){J=m}this.ticks.push(z.grpos)}if(ac>0){H=-J}else{if(v<0){H=-J;J=0}else{H=0}}if(P.length==0){P=D?("M"+J+","+z.grpos):("M"+z.grpos+","+(-J));e=D?("M"+(s-J)+","+z.grpos):("M"+z.grpos+","+(s+J))}else{P+=D?("m"+(J-ag)+","+(z.grpos-g)):("m"+(z.grpos-g)+","+(ag-J));e+=D?("m"+(ag-J)+","+(z.grpos-g)):("m"+(z.grpos-g)+","+(J-ag))}P+=D?("h"+(H-J)):("v"+(J-H));e+=D?("h"+(J-H)):("v"+(H-J));g=z.grpos;ag=H}if(P.length>0){ae.append("svg:path").attr("d",P).call(this.lineatt.func)}if((s!==0)&&(e.length>0)){ae.append("svg:path").attr("d",e).call(this.lineatt.func)}var u=D?ab:0,N=(E.fLabelSize>=1)?E.fLabelSize:Math.round(E.fLabelSize*(Y?this.pad_height():ab)),q=a.Painter.getFontDetails(E.fLabelFont,N),Z=a.Painter.root_colors[E.fLabelColor],af=3+Math.round(E.fLabelOffset*n),x=ae.append("svg:g").attr("class","axis_labels").call(q.func);this.order=0;if((this.kind=="normal")&&D&&!E.TestBit(a.EAxisBits.kNoExponent)){var G=Math.max(Math.abs(z.major[0]),Math.abs(z.major[z.major.length-1]));for(var Q=18;Q>-18;Q-=3){if(Q===0){continue}if((Q<0)&&((this.range>=0.1)||(G>=1))){break}var R=Math.pow(10,Q);if((this.range>R*9.99999)||((G>R*50)&&(this.range>R*0.05))){this.order=Q;break}}}for(var i=0;i0)?"end":"start").style("dominant-baseline","middle")}else{V.attr("x",O).attr("y",2+af*v+ac*m).attr("dy",(v>0)?".7em":"-.3em").style("text-anchor","middle")}var C=this.GetBoundarySizes(V.node());var d=(i>0)?(O-u):(D?ab/2:S/2);var M=(i0)&&(C.height>5)&&(this.kind!=="log")){k=Math.min(k,aa/C.height)}if(U){if(O+M/2-k*C.height/2<-10){V.remove()}else{V.attr("y",Math.round(O+M/2))}}}else{if((aa>0)&&(C.width>10)&&(this.kind!=="log")){k=Math.min(k,aa/C.width)}if(U){if(O+M/2-k*C.width/2>S-10){V.remove()}else{V.attr("x",Math.round(O+M/2))}}}u=O}if(this.order!==0){var I=Math.pow(10,this.order).toExponential(0);var V=x.append("svg:text").attr("fill",Z).text("\xD7"+a.Painter.formatExp(I));if(D){V.attr("x",af).attr("y",0).style("text-anchor","start").style("dominant-baseline","middle").attr("dy","-.5em")}}if((k>0)&&(k<1)){if((k<0.7)&&!D&&(v>0)){x.selectAll("text").each(function(){var r=b.select(this),h=r.attr("x"),t=r.attr("y")-5;r.attr("transform","translate("+h+","+t+") rotate(25)").style("text-anchor","start").attr("x",null).attr("y",null)});k*=3.5}q.size=Math.floor(q.size*k+0.7);x.call(q.func)}if(E.fTitle.length>0){var p=ae.append("svg:g").attr("class","axis_title"),T=(E.fTitleSize>=1)?E.fTitleSize:Math.round(E.fTitleSize*o),c=E.TestBit(a.EAxisBits.kCenterTitle),ad=E.TestBit(a.EAxisBits.kRotateTitle)?-1:1,l=a.Painter.root_colors[E.fTitleColor];this.StartTextDrawing(E.fTitleFont,T,p);var F=((ad<0)&&!W)||((ad>=0)&&W);if(D){var f=-v*Math.round(af+(2-v/10)*E.fTitleOffset*T);if((this.name=="zaxis")&&Y&&("getBoundingClientRect" in ae.node())){var L=ae.node().getBoundingClientRect();if(f0)?(-2*q.size-3):3).attr("y",0).attr("width",2*q.size+3).attr("height",ab)}else{X.attr("x",0).attr("y",0).attr("width",S).attr("height",q.size+3)}}this.position=0;if("getBoundingClientRect" in ae.node()){var B=ae.node().getBoundingClientRect(),A=this.svg_pad().node().getBoundingClientRect();this.position=B.left-A.left}};a.TAxisPainter.prototype.Redraw=function(){var i=this.GetObject(),e=Math.round(this.AxisToSvg("x",i.fX1)),q=Math.round(this.AxisToSvg("y",i.fY1)),c=Math.round(this.AxisToSvg("x",i.fX2)),p=Math.round(this.AxisToSvg("y",i.fY2)),r=c-e,l=q-p;var j=r<5,g="normal",f=null,k=i.fWmin,o=i.fWmax,m=false;if(i.fChopt.indexOf("G")>=0){f=b.scale.log();g="log"}else{f=b.scale.linear()}f.domain([k,o]);if(j){if(l>0){f.range([l,0])}else{var n=q;q=p;p=n;l=-l;m=true;f.range([0,l])}}else{if(r>0){f.range([0,r])}else{var n=e;e=c;c=n;r=-r;m=true;f.range([r,0])}}this.SetAxisConfig(j?"yaxis":"xaxis",g,f,k,o,k,o);this.RecreateDrawG(true,"text_layer");this.DrawAxis(j,this.draw_g,r,l,"translate("+e+","+p+")",m)};a.drawGaxis=function(f,e,d){var c=new a.TAxisPainter(e,false);c.SetDivId(f);c.Redraw();return c.DrawingReady()};a.THistPainter=function(c){a.TObjectPainter.call(this,c);this.histo=c;this.shrink_frame_left=0;this.draw_content=true;this.nbinsx=0;this.nbinsy=0;this.x_kind="normal";this.y_kind="normal"};a.THistPainter.prototype=Object.create(a.TObjectPainter.prototype);a.THistPainter.prototype.IsDummyHisto=function(){return(this.histo==null)||!this.draw_content||(this.options.Axis>0)};a.THistPainter.prototype.IsTProfile=function(){return this.MatchObjectType("TProfile")};a.THistPainter.prototype.IsTH2Poly=function(){return this.histo&&this.histo._typename.match(/^TH2Poly/)};a.THistPainter.prototype.Dimension=function(){if(!this.histo){return 0}if(this.histo._typename.indexOf("TH2")==0){return 2}if(this.histo._typename.indexOf("TH3")==0){return 3}return 1};a.THistPainter.prototype.DecodeOptions=function(d){if((d==null)||(d=="")){d=this.histo.fOption}var k=this.Dimension();var o={Axis:0,Bar:0,Curve:0,Error:0,Hist:0,Line:0,Mark:0,Fill:0,Same:0,Scat:0,Func:0,Star:0,Arrow:0,Box:0,Text:0,Char:0,Color:0,Contour:0,Lego:0,Surf:0,Off:0,Tri:0,Proj:0,AxisPos:0,Spec:0,Pie:0,List:0,Zscale:0,FrontBox:1,BackBox:1,Candle:"",System:a.Painter.Coord.kCARTESIAN,AutoColor:0,NoStat:0,AutoZoom:false,HighRes:0,Zero:0,Palette:0,Optimize:a.gStyle.OptimizeDraw};var l=a.Painter.clearCuts(d.toUpperCase());var g=this.root_pad();if((k===1)&&(this.histo.fSumw2.length>0)){for(var f=0;f0){o.Error=2;break}}}if(this.histo.fFunctions!==null){o.Func=1}var m=l.indexOf("PAL");if(m>=0){var j=m+3;while((j=48)&&(l.charCodeAt(j)<58)){++j}if(j>m+3){o.Palette=parseInt(l.substring(m+3,j));l=l.replace(l.substring(m,j),"")}}var e="";function c(n,i){var r=l.indexOf(n);if(r<0){return false}l=l.substr(0,r)+l.substr(r+n.length);if(i){e="";var q=r;while((qr){e=l.substr(r,q-r);l=l.substr(0,r)+l.substr(q)}}return true}if(c("NOOPTIMIZE")){o.Optimize=0}if(c("OPTIMIZE")){o.Optimize=2}if(c("AUTOCOL")){o.AutoColor=1;o.Hist=1}if(c("AUTOZOOM")){o.AutoZoom=1;o.Hist=1}if(c("NOSTAT")){o.NoStat=1}if(c("LOGX")){g.fLogx=1}if(c("LOGY")){g.fLogy=1}if(c("LOGZ")){g.fLogz=1}if(c("GRIDX")){g.fGridx=1}if(c("GRIDY")){g.fGridy=1}if(c("TICKX")){g.fTickx=1}if(c("TICKY")){g.fTicky=1}var p=l.length;if(!p){o.Hist=1}if(c("SPEC")){o.Scat=0;o.Spec=Math.max(1600,c("BF(")?parseInt(l):0)}c("GL");if(c("X+")){o.AxisPos=10}if(c("Y+")){o.AxisPos+=1}if((o.AxisPos==10||o.AxisPos==1)&&(p==2)){o.Hist=1}if(o.AxisPos==11&&(p==4)){o.Hist=1}if(c("SAMES")){if(p==5){o.Hist=1}o.Same=2}if(c("SAME")){if(p==4){o.Hist=1}o.Same=1}if(c("PIE")){o.Pie=1}if(c("CANDLE",true)){o.Candle=e}if(c("LEGO",true)){o.Scat=0;o.Lego=1;if(e.indexOf("0")>=0){o.Zero=1}if(e.indexOf("1")>=0){o.Lego=11}if(e.indexOf("2")>=0){o.Lego=12}if(e.indexOf("3")>=0){o.Lego=13}if(e.indexOf("4")>=0){o.Lego=14}if(e.indexOf("FB")>=0){o.FrontBox=0}if(e.indexOf("BB")>=0){o.BackBox=0}if(e.indexOf("Z")>=0){o.Zscale=1}}if(c("SURF",true)){o.Scat=0;o.Surf=1;if(e.indexOf("FB")>=0){o.FrontBox=0;e=e.replace("FB","")}if(e.indexOf("BB")>=0){o.BackBox=0;e=e.replace("BB","")}if((e.length>0)&&!isNaN(parseInt(e))){o.Surf=10+parseInt(e)}}if(c("TF3",true)){if(e.indexOf("FB")>=0){o.FrontBox=0}if(e.indexOf("BB")>=0){o.BackBox=0}}if(c("ISO",true)){if(e.indexOf("FB")>=0){o.FrontBox=0}if(e.indexOf("BB")>=0){o.BackBox=0}}if(c("LIST")){o.List=1}if(c("CONT",true)){if(k>1){o.Scat=0;o.Contour=1;if(!isNaN(parseInt(e))){o.Contour=10+parseInt(e)}}else{o.Hist=1}}if(c("HBAR",true)){o.Bar=20}else{if(c("BAR",true)){o.Bar=10}}if(o.Bar>0){o.Hist=0;if(!isNaN(parseInt(e))){o.Bar+=parseInt(e)}}if(c("ARR")){if(k>1){o.Arrow=1;o.Scat=0}else{o.Hist=1}}if(c("BOX1")){o.Box=11}else{if(c("BOX")){o.Box=1}}if(o.Box){if(k>1){o.Scat=0}else{o.Hist=1}}if(c("COL",true)){o.Color=1;if(e[0]=="0"){o.Color=111}if(e[0]=="1"){o.Color=1}if(e[0]=="2"){o.Color=2}if(e[0]=="3"){o.Color=3}if(e.indexOf("Z")>=0){o.Zscale=1}if(k==1){o.Hist=1}else{o.Scat=0}}if(c("CHAR")){o.Char=1;o.Scat=0}if(c("FUNC")){o.Func=2;o.Hist=0}if(c("HIST")){o.Hist=2;o.Func=0;o.Error=0}if(c("AXIS")){o.Axis=1}if(c("AXIG")){o.Axis=2}if(c("TEXT",true)){o.Text=1;o.Scat=0;var h=parseInt(e);if(!isNaN(h)){if(h<0){h=0}if(h>90){h=90}o.Text=1000+h}if(e.indexOf("N")>=0&&this.IsTH2Poly()){o.Text+=3000}}if(c("SCAT")){o.Scat=1}if(c("POL")){o.System=a.Painter.Coord.kPOLAR}if(c("CYL")){o.System=a.Painter.Coord.kCYLINDRICAL}if(c("SPH")){o.System=a.Painter.Coord.kSPHERICAL}if(c("PSR")){o.System=a.Painter.Coord.kRAPIDITY}if(c("TRI",true)){o.Scat=0;o.Color=0;o.Tri=1;if(e.indexOf("FB")>=0){o.FrontBox=0}if(e.indexOf("BB")>=0){o.BackBox=0}if(e.indexOf("ERR")>=0){o.Error=1}}if(c("AITOFF")){o.Proj=1}if(c("MERCATOR")){o.Proj=2}if(c("SINUSOIDAL")){o.Proj=3}if(c("PARABOLIC")){o.Proj=4}if(o.Proj>0){o.Scat=0;o.Contour=14}if((k==3)&&c("FB")){o.FrontBox=0}if((k==3)&&c("BB")){o.BackBox=0}if(c("A")){o.Axis=-1}if(c("B")){o.Bar=1;o.Hist=-1}if(c("C")){o.Curve=1;o.Hist=-1}if(c("F")){o.Fill=1}if(c("][")){o.Off=1;o.Hist=1}if(c("F2")){o.Fill=2}if(c("L")){o.Line=1;o.Hist=-1}if(c("P0")){o.Mark=10;o.Hist=-1}if(c("P")){o.Mark=1;o.Hist=-1}if(c("Z")){o.Zscale=1}if(c("*")){o.Star=1}if(c("H")){o.Hist=2}if(this.IsTH2Poly()){if(o.Fill+o.Line+o.Mark!=0){o.Scat=0}}if(c("E",true)){if(k==1){o.Error=1;if((e.length>0)&&!isNaN(parseInt(e[0]))){o.Error=10+parseInt(e[0])}if(e.indexOf("X0")>=0){if(o.Error==1){o.Error+=20}o.Error+=10}if(o.Text&&this.IsTProfile()){o.Text+=2000;o.Error=0}}else{if(o.Error==0){o.Error=100;o.Scat=0}if(o.Text){o.Text+=2000;o.Error=0}}}if(c("9")){o.HighRes=1}return o};a.THistPainter.prototype.GetAutoColor=function(c){if(this.options.AutoColor<=0){return c}var d=this.options.AutoColor;this.options.AutoColor=d%8+1;return a.Painter.root_colors[d]};a.THistPainter.prototype.ScanContent=function(){alert("HistPainter.prototype.ScanContent not implemented")};a.THistPainter.prototype.CheckPadRange=function(){if(!this.is_main_painter()){return}this.zoom_xmin=this.zoom_xmax=0;this.zoom_ymin=this.zoom_ymax=0;this.zoom_zmin=this.zoom_zmax=0;var e=this.root_pad();if(!e||!("fUxmin" in e)||this.create_canvas){return}var d=e.fUxmin,c=e.fUxmax,f=this.histo.fXaxis;if((this.Dimension()<3)&&((d!==0)||(c!==1))){if(e.fLogx>0){d=Math.exp(d*Math.log(10));c=Math.exp(c*Math.log(10))}if(d!==f.fXmin||c!==f.fXmax){if(d>=f.fXmin&&c<=f.fXmax){this.zoom_xmin=d;this.zoom_xmax=c}}}if(f.TestBit(a.EAxisBits.kAxisRange)){f.InvertBit(a.EAxisBits.kAxisRange);if((this.zoom_xmin===this.zoom_xmax)&&(f.fFirst!==f.fLast)&&((f.fFirst>1)||(f.fLast1?f.GetBinLowEdge(f.fFirst-1):f.fXmin;this.zoom_xmax=f.fLast0){d=Math.exp(d*Math.log(10));c=Math.exp(c*Math.log(10))}if(d!==this.histo.fYaxis.fXmin||c!==this.histo.fYaxis.fXmax){if(d>=this.histo.fYaxis.fXmin&&c<=this.histo.fYaxis.fXmax){this.zoom_ymin=d;this.zoom_ymax=c}}}};a.THistPainter.prototype.CheckHistDrawAttributes=function(){if(!this.fillatt||!this.fillatt.changed){this.fillatt=this.createAttFill(this.histo,undefined,undefined,1)}if(!this.lineatt||!this.lineatt.changed){this.lineatt=a.Painter.createAttLine(this.histo);var c=this.main_painter();if(c){var d=c.GetAutoColor(this.lineatt.color);if(d!==this.lineatt.color){this.lineatt.color=d;this.lineatt.changed=true}}}};a.THistPainter.prototype.UpdateObject=function(f){if(!this.MatchObjectType(f)){alert("JSROOT.THistPainter.UpdateObject - wrong class "+f._typename+" expected "+this.histo._typename);return false}var c=this.GetObject();c.fFillColor=f.fFillColor;c.fFillStyle=f.fFillStyle;c.fLineColor=f.fLineColor;c.fLineStyle=f.fLineStyle;c.fLineWidth=f.fLineWidth;c.fEntries=f.fEntries;c.fTsumw=f.fTsumw;c.fTsumwx=f.fTsumwx;c.fTsumwx2=f.fTsumwx2;if(this.Dimension()==2){c.fTsumwy=f.fTsumwy;c.fTsumwy2=f.fTsumwy2;c.fTsumwxy=f.fTsumwxy}c.fArray=f.fArray;c.fNcells=f.fNcells;c.fTitle=f.fTitle;c.fMinimum=f.fMinimum;c.fMaximum=f.fMaximum;c.fXaxis.fNbins=f.fXaxis.fNbins;if(!this.main_painter().zoom_changed_interactive){c.fXaxis.fXmin=f.fXaxis.fXmin;c.fXaxis.fXmax=f.fXaxis.fXmax;c.fXaxis.fFirst=f.fXaxis.fFirst;c.fXaxis.fLast=f.fXaxis.fLast;c.fXaxis.fBits=f.fXaxis.fBits;c.fYaxis.fXmin=f.fYaxis.fXmin;c.fYaxis.fXmax=f.fYaxis.fXmax;c.fYaxis.fFirst=f.fYaxis.fFirst;c.fYaxis.fLast=f.fYaxis.fLast;c.fYaxis.fBits=f.fYaxis.fBits}c.fSumw2=f.fSumw2;if(this.IsTProfile()){c.fBinEntries=f.fBinEntries}if(f.fFunctions){for(var g=0;gthis.nbinsx){this.xmax}if(g==f){return this.histo.fXaxis.fXbins[g]}var e=(f0){this.binwidthx=this.binwidthx/this.nbinsx}this.GetBinX=function(e){return this.xmin+e*this.binwidthx};this.GetIndexX=function(e,f){return Math.floor((e-this.xmin)/this.binwidthx+f)}}this.ymin=this.histo.fYaxis.fXmin;this.ymax=this.histo.fYaxis.fXmax;if(!d||(this.nbinsy==0)){return}if(this.histo.fYaxis.fXbins.length==this.nbinsy+1){this.regulary=false;this.GetBinY=function(f){var g=Math.round(f);if(g<=0){return this.ymin}if(g>this.nbinsy){this.ymax}if(g==f){return this.histo.fYaxis.fXbins[g]}var e=(f0){this.binwidthy=this.binwidthy/this.nbinsy}this.GetBinY=function(e){return this.ymin+e*this.binwidthy};this.GetIndexY=function(f,e){return Math.floor((f-this.ymin)/this.binwidthy+e)}}if(!c||(this.nbinsz==0)){return}if(this.histo.fZaxis.fXbins.length==this.nbinsz+1){this.regularz=false;this.GetBinZ=function(f){var g=Math.round(f);if(g<=0){return this.zmin}if(g>this.nbinsz){this.zmax}if(g==f){return this.histo.fZaxis.fXbins[g]}var e=(f0){this.binwidthz=this.binwidthz/this.nbinsz}this.GetBinZ=function(e){return this.zmin+e*this.binwidthz};this.GetIndexZ=function(f,e){return Math.floor((f-this.zmin)/this.binwidthz+e)}}};a.THistPainter.prototype.CreateXY=function(){if(!this.is_main_painter()){this.x=this.main_painter().x;this.y=this.main_painter().y;return}this.swap_xy=false;if(this.options.Bar>=20){this.swap_xy=true}this.logx=this.logy=false;var c=this.frame_width(),e=this.frame_height(),f=this.root_pad();if(this.histo.fXaxis.fTimeDisplay){this.x_kind="time";this.timeoffsetx=a.Painter.getTimeOffset(this.histo.fXaxis);this.ConvertX=function(g){return new Date(this.timeoffsetx+g*1000)};this.RevertX=function(g){return(this.x.invert(g)-this.timeoffsetx)/1000}}else{this.x_kind=(this.histo.fXaxis.fLabels==null)?"normal":"labels";this.ConvertX=function(g){return g};this.RevertX=function(g){return this.x.invert(g)}}this.scale_xmin=this.xmin;this.scale_xmax=this.xmax;if(this.zoom_xmin!=this.zoom_xmax){this.scale_xmin=this.zoom_xmin;this.scale_xmax=this.zoom_xmax}if(this.x_kind=="time"){this.x=b.time.scale()}else{if(this.swap_xy?f.fLogy:f.fLogx){this.logx=true;if(this.scale_xmax<=0){this.scale_xmax=0}if((this.scale_xmin<=0)&&(this.nbinsx>0)){for(var d=0;d0){break}}}if((this.scale_xmin<=0)||(this.scale_xmin>=this.scale_xmax)){this.scale_xmin=this.scale_xmax*0.0001}this.x=b.scale.log()}else{this.x=b.scale.linear()}}this.x.domain([this.ConvertX(this.scale_xmin),this.ConvertX(this.scale_xmax)]).range(this.swap_xy?[e,0]:[0,c]);if(this.x_kind=="time"){this.grx=function(g){return this.x(this.ConvertX(g))}}else{if(this.logx){this.grx=function(g){return(g0)){for(var d=0;d0){break}}}if((this.scale_ymin<=0)&&("ymin_nz" in this)&&(this.ymin_nz>0)){this.scale_ymin=0.3*this.ymin_nz}if((this.scale_ymin<=0)||(this.scale_ymin>=this.scale_ymax)){this.scale_ymin=0.000001*this.scale_ymax}this.y=b.scale.log()}else{if(this.y_kind=="time"){this.y=b.time.scale()}else{this.y=b.scale.linear()}}this.y.domain([this.ConvertY(this.scale_ymin),this.ConvertY(this.scale_ymax)]).range(this.swap_xy?[0,c]:[e,0]);if(this.y_kind=="time"){this.gry=function(g){return this.y(this.ConvertY(g))}}else{if(this.logy){this.gry=function(g){return(g0){e.append("svg:path").attr("class","xgrid").attr("d",d).style("stroke","black").style("stroke-width",1).style("stroke-dasharray",a.Painter.root_line_styles[11])}}if(g&&g.fGridy&&this.y_handle){d="";for(var i=0;i0){e.append("svg:path").attr("class","ygrid").attr("d",d).style("stroke","black").style("stroke-width",1).style("stroke-dasharray",a.Painter.root_line_styles[11])}}};a.THistPainter.prototype.DrawBins=function(){alert("HistPainter.DrawBins not implemented")};a.THistPainter.prototype.AxisAsText=function(c,d){if(c=="x"){if(this.x_kind=="time"){d=this.ConvertX(d)}if(this.x_handle&&("format" in this.x_handle)){return this.x_handle.format(d)}return d.toPrecision(4)}if(c=="y"){if(this.y_kind=="time"){d=this.ConvertY(d)}if(this.y_handle&&("format" in this.y_handle)){return this.y_handle.format(d)}return d.toPrecision(4)}return d.toPrecision(4)};a.THistPainter.prototype.DrawAxes=function(k){if(!this.is_main_painter()){return}var i=this.svg_frame().select(".axis_layer"),l=this.frame_width(),g=this.frame_height(),e=this.root_pad();this.x_handle=new a.TAxisPainter(this.histo.fXaxis,true);this.x_handle.SetDivId(this.divid,-1);this.x_handle.SetAxisConfig("xaxis",(this.logx&&(this.x_kind!=="time"))?"log":this.x_kind,this.x,this.xmin,this.xmax,this.scale_xmin,this.scale_xmax);this.y_handle=new a.TAxisPainter(this.histo.fYaxis,true);this.y_handle.SetDivId(this.divid,-1);this.y_handle.SetAxisConfig("yaxis",(this.logy&&this.y_kind!=="time")?"log":this.y_kind,this.y,this.ymin,this.ymax,this.scale_ymin,this.scale_ymax);var j=this.swap_xy?this.y_handle:this.x_handle;var c=this.swap_xy?this.x_handle:this.y_handle;j.DrawAxis(false,i,l,g,"translate(0,"+g+")",false,e.fTickx?-g:0);c.DrawAxis(true,i,l,g,undefined,false,e.fTicky?l:0);if(k){return}var f=0,d=c.position;if((-0.2*l0)&&(d<0.3*l)&&(this.shrink_frame_left>0)&&(d/l>this.shrink_frame_left)){f=-this.shrink_frame_left;this.shrink_frame_left=0}}if(f!=0){this.frame_painter().Shrink(f,0);this.frame_painter().Redraw();this.CreateXY();this.DrawAxes(true)}};a.THistPainter.prototype.DrawTitle=function(){if(!this.is_main_painter()){return}var d=this.FindPainterFor(null,"title");var e=(d!==null)?d.GetObject():null;if(e===null){e=this.FindInPrimitives("title")}if((e!==null)&&(e._typename!=="TPaveText")){e=null}var c=!this.histo.TestBit(a.TH1StatusBits.kNoTitle);if(e!==null){e.Clear();if(c){e.AddText(this.histo.fTitle)}}else{if(c&&!d&&(this.histo.fTitle.length>0)){e=a.Create("TPaveText");a.extend(e,{fName:"title",fX1NDC:0.28,fY1NDC:0.94,fX2NDC:0.72,fY2NDC:0.99});e.AddText(this.histo.fTitle);a.Painter.drawPaveText(this.divid,e)}}};a.THistPainter.prototype.ToggleStat=function(c){var d=this.FindStat(),e=null;if(d==null){if(c=="only-check"){return false}d=this.CreateStat()}else{e=this.FindPainterFor(d)}if(c=="only-check"){return e?e.Enabled:false}if(e){e.Enabled=!e.Enabled;e.Redraw();return e.Enabled}a.draw(this.divid,d,"onpad:"+this.pad_name);return true};a.THistPainter.prototype.IsAxisZoomed=function(c){var d=this.main_painter();if(d==null){d=this}if(c==="x"){return d.zoom_xmin!=d.zoom_xmax}if(c==="y"){return d.zoom_ymin!=d.zoom_ymax}return false};a.THistPainter.prototype.GetSelectIndex=function(e,l,k){var i=0,h=this.main_painter();if(h==null){h=this}var f=this["nbins"+e];if(!f){f=0}if(!k){k=0}var d="GetIndex"+e.toUpperCase(),g=h["zoom_"+e+"min"],j=h["zoom_"+e+"max"];if((g!=j)&&(d in this)){if(l=="left"){i=this[d](g,k)}else{i=this[d](j,k+0.5)}}else{i=(l=="left")?0:f}var c;if(this.histo){c=this.histo["f"+e.toUpperCase()+"axis"]}if(c){if((c.fFirst===c.fLast)||!c.TestBit(a.EAxisBits.kAxisRange)||((c.fFirst<=1)&&(c.fLast>=f))){c=undefined}}if(l=="left"){if(i<0){i=0}if(c&&(c.fFirst>1)&&(if){i=f}if(c&&(c.fLast<=f)&&(i>c.fLast)){i=c.fLast}}return i};a.THistPainter.prototype.FindStat=function(){if(this.histo.fFunctions!==null){for(var c=0;c=this.histo.fFunctions.arr.length)){return a.CallBack(i)}var g=this.histo.fFunctions.arr[h],d=this.histo.fFunctions.opt[h],f=false,e=this.FindPainterFor(g);if(e===null){if(g._typename==="TPaveText"||g._typename==="TPaveStats"){f=!this.histo.TestBit(a.TH1StatusBits.kNoStats)&&(this.options.NoStat!=1)}else{if(g._typename==="TF1"){f=!g.TestBit(a.BIT(9))}else{f=(g._typename!=="TPaletteAxis")}}}if(f){var c=a.draw(this.divid,g,d);if(c){return c.WhenReady(this.DrawNextFunction.bind(this,h+1,i))}}this.DrawNextFunction(h+1,i)};a.THistPainter.prototype.UnzoomUserRange=function(g,f,e){if(!this.histo){return false}function c(h){if(!h){return false}if(!h.TestBit(a.EAxisBits.kAxisRange)){return false}if(h.fFirst===h.fLast){return false}if((h.fFirst<=1)&&(h.fLast>=h.fNbins)){return false}h.InvertBit(a.EAxisBits.kAxisRange);return true}var d=false;if(g){d|=c(this.histo.fXaxis)}if(f){d|=c(this.histo.fYaxis)}if(e){d|=c(this.histo.fZaxis)}return d};a.THistPainter.prototype.ToggleLog=function(c){var f=this.main_painter(),e=this.root_pad();if(!f){f=this}var d=e["fLog"+c];if(!d&&(this[c+"_kind"]=="labels")){return}e["fLog"+c]=d?0:1;f.RedrawPad()};a.THistPainter.prototype.Zoom=function(d,m,o,h,n,p){var k=this.main_painter(),j=(d!==m),g=(o!==h),e=(n!==p),c=false,r=false,q=false;if(j){var i=0;if(d<=k.xmin){d=k.xmin;i++}if(m>=k.xmax){m=k.xmax;i++}if(i===2){j=false;c=true}}else{c=(d===m)&&(d===0)}if(g){var i=0;if(o<=k.ymin){o=k.ymin;i++}if(h>=k.ymax){h=k.ymax;i++}if(i===2){g=false;r=true}}else{r=(o===h)&&(o===0)}if(e){var i=0;if(n<=k.zmin){n=k.zmin;i++}if(p>=k.zmax){p=k.zmax;i++}if(i===2){e=false;q=true}}else{q=(n===p)&&(n===0)}var l=false;if(j||g||e){k.ForEachPainter(function(s){if(j&&s.CanZoomIn("x",d,m)){k.zoom_xmin=d;k.zoom_xmax=m;l=true;j=false}if(g&&s.CanZoomIn("y",o,h)){k.zoom_ymin=o;k.zoom_ymax=h;l=true;g=false}if(e&&s.CanZoomIn("z",n,p)){k.zoom_zmin=n;k.zoom_zmax=p;l=true;e=false}})}if(c||r||q){if(c){if(k.zoom_xmin!==k.zoom_xmax){l=true}k.zoom_xmin=k.zoom_xmax=0}if(r){if(k.zoom_ymin!==k.zoom_ymax){l=true}k.zoom_ymin=k.zoom_ymax=0}if(q){if(k.zoom_zmin!==k.zoom_zmax){l=true}k.zoom_zmin=k.zoom_zmax=0}if(!l){l=k.UnzoomUserRange(c,r,q);var f=this.pad_painter(true);if(f&&f.painters){f.painters.forEach(function(s){if(s&&(s!==k)&&(typeof s.UnzoomUserRange=="function")){if(s.UnzoomUserRange(c,r,q)){l=true}}})}}}if(l){this.RedrawPad()}return l};a.THistPainter.prototype.Unzoom=function(e,d,c){if(typeof e==="undefined"){e=true;d=true;c=true}else{if(typeof e==="string"){c=e.indexOf("z")>=0;d=e.indexOf("y")>=0;e=e.indexOf("x")>=0}}if(e||d||e){this.zoom_changed_interactive=true}return this.Zoom(e?0:undefined,e?0:undefined,d?0:undefined,d?0:undefined,c?0:undefined,c?0:undefined)};a.THistPainter.prototype.clearInteractiveElements=function(){a.Painter.closeMenu();if(this.zoom_rect!=null){this.zoom_rect.remove();this.zoom_rect=null}this.zoom_kind=0;this.SwitchTooltip(true)};a.THistPainter.prototype.mouseDoubleClick=function(){b.event.preventDefault();var c=b.mouse(this.svg_frame().node());this.clearInteractiveElements();var d="xyz";if(c[0]<0){d="y"}else{if(c[1]>this.frame_height()){d="x"}}this.Unzoom(d)};a.THistPainter.prototype.startRectSel=function(){if(this.zoom_kind>100){return}if((b.event.which||b.event.button)!==1){return}b.event.preventDefault();this.clearInteractiveElements();this.zoom_origin=b.mouse(this.svg_frame().node());this.zoom_curr=[Math.max(0,Math.min(this.frame_width(),this.zoom_origin[0])),Math.max(0,Math.min(this.frame_height(),this.zoom_origin[1]))];if(this.zoom_origin[0]<0){this.zoom_kind=3;this.zoom_origin[0]=0;this.zoom_origin[1]=this.zoom_curr[1];this.zoom_curr[0]=this.frame_width();this.zoom_curr[1]+=1}else{if(this.zoom_origin[1]>this.frame_height()){this.zoom_kind=2;this.zoom_origin[0]=this.zoom_curr[0];this.zoom_origin[1]=0;this.zoom_curr[0]+=1;this.zoom_curr[1]=this.frame_height()}else{this.zoom_kind=1;this.zoom_origin[0]=this.zoom_curr[0];this.zoom_origin[1]=this.zoom_curr[1]}}b.select(window).on("mousemove.zoomRect",this.moveRectSel.bind(this)).on("mouseup.zoomRect",this.endRectSel.bind(this),true);this.zoom_rect=null;this.SwitchTooltip(false);b.event.stopPropagation()};a.THistPainter.prototype.moveRectSel=function(){if((this.zoom_kind==0)||(this.zoom_kind>100)){return}b.event.preventDefault();var c=b.mouse(this.svg_frame().node());c[0]=Math.max(0,Math.min(this.frame_width(),c[0]));c[1]=Math.max(0,Math.min(this.frame_height(),c[1]));switch(this.zoom_kind){case 1:this.zoom_curr[0]=c[0];this.zoom_curr[1]=c[1];break;case 2:this.zoom_curr[0]=c[0];break;case 3:this.zoom_curr[1]=c[1];break}if(this.zoom_rect===null){this.zoom_rect=this.svg_frame().append("rect").attr("class","zoom").attr("pointer-events","none")}this.zoom_rect.attr("x",Math.min(this.zoom_origin[0],this.zoom_curr[0])).attr("y",Math.min(this.zoom_origin[1],this.zoom_curr[1])).attr("width",Math.abs(this.zoom_curr[0]-this.zoom_origin[0])).attr("height",Math.abs(this.zoom_curr[1]-this.zoom_origin[1]))};a.THistPainter.prototype.endRectSel=function(){if((this.zoom_kind==0)||(this.zoom_kind>100)){return}b.event.preventDefault();b.select(window).on("mousemove.zoomRect",null).on("mouseup.zoomRect",null);var e=b.mouse(this.svg_frame().node());e[0]=Math.max(0,Math.min(this.frame_width(),e[0]));e[1]=Math.max(0,Math.min(this.frame_height(),e[1]));var f=[true,true];switch(this.zoom_kind){case 1:this.zoom_curr[0]=e[0];this.zoom_curr[1]=e[1];break;case 2:this.zoom_curr[0]=e[0];f[1]=false;break;case 3:this.zoom_curr[1]=e[1];f[0]=false;break}var c,h,j,d,g=false,k=this.swap_xy?1:0,i=1-k;if(f[k]&&(Math.abs(this.zoom_curr[k]-this.zoom_origin[k])>10)){c=Math.min(this.RevertX(this.zoom_origin[k]),this.RevertX(this.zoom_curr[k]));h=Math.max(this.RevertX(this.zoom_origin[k]),this.RevertX(this.zoom_curr[k]));g=true}if(f[i]&&(Math.abs(this.zoom_curr[i]-this.zoom_origin[i])>10)){j=Math.min(this.RevertY(this.zoom_origin[i]),this.RevertY(this.zoom_curr[i]));d=Math.max(this.RevertY(this.zoom_origin[i]),this.RevertY(this.zoom_curr[i]));g=true}this.clearInteractiveElements();if(g){this.zoom_changed_interactive=true;this.Zoom(c,h,j,d)}};a.THistPainter.prototype.startTouchZoom=function(){if(this.zoom_kind!=0){b.event.preventDefault();b.event.stopPropagation();return}var d=b.touches(this.svg_frame().node());this.touch_cnt+=1;if(d.length==1){var e=new Date();var f=e.getTime()-this.last_touch.getTime();this.last_touch=e;if((f<300)&&(this.zoom_curr!=null)&&(Math.abs(this.zoom_curr[0]-d[0][0])<30)&&(Math.abs(this.zoom_curr[1]-d[0][1])<30)){b.event.preventDefault();b.event.stopPropagation();this.clearInteractiveElements();this.Unzoom("xyz");this.last_touch=new Date(0);this.svg_frame().on("touchcancel",null).on("touchend",null,true)}else{if(a.gStyle.ContextMenu){this.zoom_curr=d[0];this.svg_frame().on("touchcancel",this.endTouchSel.bind(this)).on("touchend",this.endTouchSel.bind(this));b.event.preventDefault();b.event.stopPropagation()}}}if(d.length!=2){return}b.event.preventDefault();b.event.stopPropagation();this.clearInteractiveElements();this.svg_frame().on("touchcancel",null).on("touchend",null);var c=d[0],g=d[1];this.zoom_curr=[Math.min(c[0],g[0]),Math.min(c[1],g[1])];this.zoom_origin=[Math.max(c[0],g[0]),Math.max(c[1],g[1])];if(this.zoom_curr[0]<0){this.zoom_kind=103;this.zoom_curr[0]=0;this.zoom_origin[0]=this.frame_width()}else{if(this.zoom_origin[1]>this.frame_height()){this.zoom_kind=102;this.zoom_curr[1]=0;this.zoom_origin[1]=this.frame_height()}else{this.zoom_kind=101}}this.SwitchTooltip(false);this.zoom_rect=this.svg_frame().append("rect").attr("class","zoom").attr("id","zoomRect").attr("x",this.zoom_curr[0]).attr("y",this.zoom_curr[1]).attr("width",this.zoom_origin[0]-this.zoom_curr[0]).attr("height",this.zoom_origin[1]-this.zoom_curr[1]);b.select(window).on("touchmove.zoomRect",this.moveTouchSel.bind(this)).on("touchcancel.zoomRect",this.endTouchSel.bind(this)).on("touchend.zoomRect",this.endTouchSel.bind(this))};a.THistPainter.prototype.moveTouchSel=function(){if(this.zoom_kind<100){return}b.event.preventDefault();var d=b.touches(this.svg_frame().node());if(d.length!=2){return this.clearInteractiveElements()}var c=d[0],e=d[1];if(this.zoom_kind!=103){this.zoom_curr[0]=Math.min(c[0],e[0]);this.zoom_origin[0]=Math.max(c[0],e[0])}if(this.zoom_kind!=102){this.zoom_curr[1]=Math.min(c[1],e[1]);this.zoom_origin[1]=Math.max(c[1],e[1])}this.zoom_rect.attr("x",this.zoom_curr[0]).attr("y",this.zoom_curr[1]).attr("width",this.zoom_origin[0]-this.zoom_curr[0]).attr("height",this.zoom_origin[1]-this.zoom_curr[1]);if((this.zoom_origin[0]-this.zoom_curr[0]>10)||(this.zoom_origin[1]-this.zoom_curr[1]>10)){this.SwitchTooltip(false)}b.event.stopPropagation()};a.THistPainter.prototype.endTouchSel=function(){this.svg_frame().on("touchcancel",null).on("touchend",null);if(this.zoom_kind===0){b.event.preventDefault();var d=new Date();var k=d.getTime()-this.last_touch.getTime();if((k>500)&&(k<2000)&&!this.frame_painter().IsTooltipShown()){this.ShowContextMenu("main",{clientX:this.zoom_curr[0],clientY:this.zoom_curr[1]});this.last_touch=new Date(0)}else{this.clearInteractiveElements()}}if(this.zoom_kind<100){return}b.event.preventDefault();b.select(window).on("touchmove.zoomRect",null).on("touchend.zoomRect",null).on("touchcancel.zoomRect",null);var c,j,l,e,i=false,f=this.swap_xy?1:0,h=1-f,g=[true,true];if(this.zoom_kind===102){g[1]=false}if(this.zoom_kind===103){g[0]=false}if(g[f]&&(Math.abs(this.zoom_curr[f]-this.zoom_origin[f])>10)){c=Math.min(this.RevertX(this.zoom_origin[f]),this.RevertX(this.zoom_curr[f]));j=Math.max(this.RevertX(this.zoom_origin[f]),this.RevertX(this.zoom_curr[f]));i=true}if(g[h]&&(Math.abs(this.zoom_curr[h]-this.zoom_origin[h])>10)){l=Math.min(this.RevertY(this.zoom_origin[h]),this.RevertY(this.zoom_curr[h]));e=Math.max(this.RevertY(this.zoom_origin[h]),this.RevertY(this.zoom_curr[h]));i=true}this.clearInteractiveElements();this.last_touch=new Date(0);if(i){this.zoom_changed_interactive=true;this.Zoom(c,j,l,e)}b.event.stopPropagation()};a.THistPainter.prototype.mouseWheel=function(){b.event.stopPropagation();var h=0;switch(b.event.deltaMode){case 0:h=b.event.deltaY/this.pad_height()*2;break;case 1:h=b.event.deltaY/this.pad_height()*40;break;case 2:h=b.event.deltaY/this.pad_height()*200;break}if(h===0){return}b.event.preventDefault();this.clearInteractiveElements();if(h<-0.2){h=-0.2}else{if(h>0.2){h=0.2}}var e={name:"x",ignore:false},d={name:"y",ignore:(this.Dimension()==1)},f=b.mouse(this.svg_frame().node()),c=this;function g(k,i,m){k.min=k.max=undefined;k.changed=false;if(m&&k.ignore){return}k.min=c["scale_"+k.name+"min"];k.max=c["scale_"+k.name+"max"];if((k.min===k.max)&&(h<0)){k.min=c[k.name+"min"];k.max=c[k.name+"max"]}if(k.min>=k.max){return}if((i>0)&&(i<1)){if(c["log"+k.name]){var j=(k.min>0)?a.log10(k.max/k.min):2;if(j>10){j=10}else{if(j<1.5){j=1.5}}k.min=k.min/Math.pow(j,h*i);k.max=k.max*Math.pow(j,h*(1-i))}else{var l=(k.max-k.min);if(h>0){l=1.001*l/(1-h)}k.min+=-h*i*l;k.max-=-h*(1-i)*l}if(k.min>=k.max){k.min=k.max=undefined}}else{k.min=k.max=undefined}k.changed=((k.min!==undefined)&&(k.max!==undefined))}g(this.swap_xy?d:e,f[0]/this.frame_width(),(f[1]<=this.frame_height()));g(this.swap_xy?e:d,1-f[1]/this.frame_height(),(f[0]>=0));this.Zoom(e.min,e.max,d.min,d.max);if(e.changed||d.changed){this.zoom_changed_interactive=true}};a.THistPainter.prototype.AddInteractive=function(){if((!a.gStyle.Zooming&&!a.gStyle.ContextMenu)||!this.is_main_painter()){return}var c=this.svg_frame();if(c.empty()||c.property("interactive_set")){return}this.last_touch=new Date(0);this.zoom_kind=0;this.zoom_rect=null;this.zoom_origin=null;this.zoom_curr=null;this.touch_cnt=0;if(a.gStyle.Zooming){c.on("mousedown",this.startRectSel.bind(this));c.on("dblclick",this.mouseDoubleClick.bind(this));c.on("wheel",this.mouseWheel.bind(this))}if(a.touches&&(a.gStyle.Zooming||a.gStyle.ContextMenu)){c.on("touchstart",this.startTouchZoom.bind(this))}if(a.gStyle.ContextMenu){if(a.touches){c.selectAll(".xaxis_container").on("touchstart",this.startTouchMenu.bind(this,"x"));c.selectAll(".yaxis_container").on("touchstart",this.startTouchMenu.bind(this,"y"))}c.on("contextmenu",this.ShowContextMenu.bind(this));c.selectAll(".xaxis_container").on("contextmenu",this.ShowContextMenu.bind(this,"x"));c.selectAll(".yaxis_container").on("contextmenu",this.ShowContextMenu.bind(this,"y"))}c.property("interactive_set",true)};a.THistPainter.prototype.ShowContextMenu=function(j,r,k){if(("zoom_kind" in this)&&(this.zoom_kind>100)){return}var p=this,l=false;if(!r){b.event.preventDefault();b.event.stopPropagation();r=b.event;if(j===undefined){var d=b.mouse(this.svg_frame().node());var i=b.touches(this.svg_frame().node());var c=null,g=this.pad_painter(true),m=this.frame_painter(),f=null;if(i.length===1){c={x:i[0][0],y:i[0][1],touch:true}}else{if(d.length===2){c={x:d[0],y:d[1],touch:false}}}if((c!==null)&&(g!==null)){c.painters=true;var e=g.GetTooltips(c);var q=1000;for(var h=0;h0)&&(c.x<20)&&(c.y>0)&&(c.y<20)}}}p.ctx_menu_evnt=r;a.Painter.createMenu(function(s){s.painter=this;var n=this.FillContextMenu(s,j,k);if(m&&(!n||(l&&(j!=="frame")))){n=m.FillContextMenu(s)}if(n){this.SwitchTooltip(false);s.show(this.ctx_menu_evnt,this.SwitchTooltip.bind(this,true))}delete this.ctx_menu_evnt}.bind(p))};a.THistPainter.prototype.ChangeUserRange=function(c){var g=this.histo["f"+c+"axis"];if(!g){return}var f="[1,"+g.fNbins+"]";if(g.TestBit(a.EAxisBits.kAxisRange)){f="["+g.fFirst+","+g.fLast+"]"}var e=prompt("Enter user range for axis "+c+" like [1,"+g.fNbins+"]",f);if(e==null){return}e=JSON.parse(e);if(!e||(e.length!=2)||isNaN(e[0])||isNaN(e[1])){return}g.fFirst=parseInt(e[0]);g.fLast=parseInt(e[1]);var d=(g.fFirst=1)&&(g.fLast<=g.fNbins);if(d!=g.TestBit(a.EAxisBits.kAxisRange)){g.InvertBit(a.EAxisBits.kAxisRange)}this.Redraw()};a.THistPainter.prototype.FillContextMenu=function(g,e,f){this.clearInteractiveElements();if((e=="x")||(e=="y")||(e=="z")){var c=this.histo.fXaxis;if(e=="y"){c=this.histo.fYaxis}else{if(e=="z"){c=f?f:this.histo.fZaxis}}g.add("header: "+e.toUpperCase()+" axis");g.add("Unzoom",this.Unzoom.bind(this,e));g.addchk(this.options["Log"+e],"SetLog"+e,this.ToggleLog.bind(this,e));g.addchk(c.TestBit(a.EAxisBits.kMoreLogLabels),"More log",function(){c.InvertBit(a.EAxisBits.kMoreLogLabels);this.RedrawPad()});g.addchk(c.TestBit(a.EAxisBits.kNoExponent),"No exponent",function(){c.InvertBit(a.EAxisBits.kNoExponent);this.RedrawPad()});if((e==="z")&&(this.options.Zscale>0)){if(this.FillPaletteMenu){this.FillPaletteMenu(g)}}if(c!=null){g.add("sub:Labels");g.addchk(c.TestBit(a.EAxisBits.kCenterLabels),"Center",function(){c.InvertBit(a.EAxisBits.kCenterLabels);this.RedrawPad()});this.AddColorMenuEntry(g,"Color",c.fLabelColor,function(h){c.fLabelColor=parseInt(h);this.RedrawPad()});this.AddSizeMenuEntry(g,"Offset",0,0.1,0.01,c.fLabelOffset,function(h){c.fLabelOffset=parseFloat(h);this.RedrawPad()});this.AddSizeMenuEntry(g,"Size",0.02,0.11,0.01,c.fLabelSize,function(h){c.fLabelSize=parseFloat(h);this.RedrawPad()});g.add("endsub:");g.add("sub:Title");g.add("SetTitle",function(){var h=prompt("Enter axis title",c.fTitle);if(h!==null){c.fTitle=h;this.RedrawPad()}});g.addchk(c.TestBit(a.EAxisBits.kCenterTitle),"Center",function(){c.InvertBit(a.EAxisBits.kCenterTitle);this.RedrawPad()});g.addchk(c.TestBit(a.EAxisBits.kRotateTitle),"Rotate",function(){c.InvertBit(a.EAxisBits.kRotateTitle);this.RedrawPad()});this.AddColorMenuEntry(g,"Color",c.fTitleColor,function(h){c.fTitleColor=parseInt(h);this.RedrawPad()});this.AddSizeMenuEntry(g,"Offset",0,3,0.2,c.fTitleOffset,function(h){c.fTitleOffset=parseFloat(h);this.RedrawPad()});this.AddSizeMenuEntry(g,"Size",0.02,0.11,0.01,c.fTitleSize,function(h){c.fTitleSize=parseFloat(h);this.RedrawPad()});g.add("endsub:")}g.add("sub:Ticks");this.AddColorMenuEntry(g,"Color",c.fLineColor,function(h){c.fLineColor=parseInt(h);this.RedrawPad()});this.AddColorMenuEntry(g,"Color",c.fAxisColor,function(h){c.fAxisColor=parseInt(h);this.RedrawPad()});this.AddSizeMenuEntry(g,"Size",-0.05,0.055,0.01,c.fTickLength,function(h){c.fTickLength=parseFloat(h);this.RedrawPad()});g.add("endsub:");return true}if(e=="frame"){var d=this.frame_painter();if(d){return d.FillContextMenu(g)}}g.add("header:"+this.histo._typename+"::"+this.histo.fName);if(this.draw_content){g.addchk(this.ToggleStat("only-check"),"Show statbox",function(){this.ToggleStat()});if(this.Dimension()==1){g.add("User range X","X",this.ChangeUserRange)}else{g.add("sub:User ranges");g.add("X","X",this.ChangeUserRange);g.add("Y","Y",this.ChangeUserRange);if(this.Dimension()>2){g.add("Z","Z",this.ChangeUserRange)}g.add("endsub:")}if(typeof this.FillHistContextMenu=="function"){this.FillHistContextMenu(g)}}if((this.options.Lego>0)||(this.Dimension()===3)){if(g.size()>0){g.add("separator")}g.addchk(this.enable_tooltip,"Show tooltips",function(){this.enable_tooltip=!this.enable_tooltip});if(this.enable_tooltip){g.addchk(this.enable_hightlight,"Hightlight bins",function(){this.enable_hightlight=!this.enable_hightlight;if(!this.enable_hightlight&&this.BinHighlight3D){this.BinHighlight3D(null)}})}g.addchk(this.options.FrontBox,"Front box",function(){this.options.FrontBox=!this.options.FrontBox;if(this.Render3D){this.Render3D()}});g.addchk(this.options.BackBox,"Back box",function(){this.options.BackBox=!this.options.BackBox;if(this.Render3D){this.Render3D()}});if(this.draw_content){g.addchk(this.options.Zero,"Suppress zeros",function(){this.options.Zero=!this.options.Zero;this.RedrawPad()});if((this.options.Lego==12)||(this.options.Lego==14)){g.addchk(this.options.Zscale,"Z scale",function(){this.ToggleColz()});if(this.FillPaletteMenu){this.FillPaletteMenu(g)}}}if(this.control&&typeof this.control.reset==="function"){g.add("Reset camera",function(){this.control.reset()})}}this.FillAttContextMenu(g);return true};a.THistPainter.prototype.ButtonClick=function(c){if(!this.is_main_painter()){return false}switch(c){case"ToggleZoom":if((this.zoom_xmin!==this.zoom_xmax)||(this.zoom_ymin!==this.zoom_ymax)||(this.zoom_zmin!==this.zoom_zmax)){this.Unzoom();return true}if(this.draw_content&&("AutoZoom" in this)&&(this.Dimension()<3)){this.AutoZoom();return true}break;case"ToggleLogX":this.ToggleLog("x");break;case"ToggleLogY":this.ToggleLog("y");break;case"ToggleLogZ":this.ToggleLog("z");break;case"ToggleStatBox":this.ToggleStat();return true;break}return false};a.THistPainter.prototype.FillToolbar=function(){var c=this.pad_painter(true);if(c===null){return}c.AddButton(a.ToolbarIcons.auto_zoom,"Toggle between unzoom and autozoom-in","ToggleZoom");c.AddButton(a.ToolbarIcons.arrow_right,"Toggle log x","ToggleLogX");c.AddButton(a.ToolbarIcons.arrow_up,"Toggle log y","ToggleLogY");if(this.Dimension()>1){c.AddButton(a.ToolbarIcons.arrow_diag,"Toggle log z","ToggleLogZ")}if(this.draw_content){c.AddButton(a.ToolbarIcons.statbox,"Toggle stat box","ToggleStatBox")}};a.TH1Painter=function(c){a.THistPainter.call(this,c)};a.TH1Painter.prototype=Object.create(a.THistPainter.prototype);a.TH1Painter.prototype.ScanContent=function(){this.nbinsx=this.histo.fXaxis.fNbins;this.nbinsy=0;this.CreateAxisFuncs(false);var f=0,c=0,m=0,k=0,l=true,d=this.GetSelectIndex("x","left"),o=this.GetSelectIndex("x","right"),e=this.IsTProfile(),n,g;for(var j=0;j=o)){continue}if(n>0){if((c==0)||(n0)?this.histo.getBinError(j+1):0;f=Math.min(f,n-g);m=Math.max(m,n+g)}if(e){k+=this.histo.fBinEntries[0]+this.histo.fBinEntries[this.nbinsx+1]}else{k+=this.histo.getBinContent(0)+this.histo.getBinContent(this.nbinsx+1)}this.stat_entries=k;if(this.histo.fEntries>1){this.stat_entries=this.histo.fEntries}this.hmin=f;this.hmax=m;this.ymin_nz=c;if((this.nbinsx==0)||((Math.abs(f)<1e-300&&Math.abs(m)<1e-300))){this.draw_content=false;f=this.ymin;m=this.ymax}else{this.draw_content=true}if(f>=m){if(f==0){this.ymin=0;this.ymax=1}else{if(f<0){this.ymin=2*f;this.ymax=0}else{this.ymin=0;this.ymax=f*2}}}else{var p=(m-f)*0.05;this.ymin=f-p;if((this.ymin<0)&&(f>=0)){this.ymin=0}this.ymax=m+p}f=m=null;var h=false;if(this.histo.fMinimum!=-1111){f=this.histo.fMinimum;if(fthis.ymax){this.ymax=m}else{h=true}}if(h){this.zoom_ymin=(f==null)?this.ymin:f;this.zoom_ymax=(m==null)?this.ymax:m}if(!this.options.Bar&&!this.options.Hist&&!this.options.Error&&!this.options.Same&&!this.options.Lego){this.draw_content=false}if(this.options.Axis>0){this.draw_content=false}};a.TH1Painter.prototype.CountStat=function(o){var e=this.IsTProfile();var f=0,l=0,r=0,k=0,j=0;var d=this.GetSelectIndex("x","left");var q=this.GetSelectIndex("x","right");var c=0,p=0,h=null,n=null;for(var g=d;gn)){h=c;n=p}f+=p;l+=p*c;r+=p*c*c}if(!this.IsAxisZoomed("x")&&(this.histo.fTsumw>0)){f=this.histo.fTsumw;l=this.histo.fTsumwx;r=this.histo.fTsumwx2}var m={meanx:0,meany:0,rmsx:0,rmsy:0,integral:f,entries:this.stat_entries,xmax:0,wmax:0};if(f>0){m.meanx=l/f;m.meany=k/f;m.rmsx=Math.sqrt(r/f-m.meanx*m.meanx);m.rmsy=Math.sqrt(j/f-m.meany*m.meany)}if(h!=null){m.xmax=h;m.wmax=n}return m};a.TH1Painter.prototype.FillStatistic=function(w,k,x){if(!this.histo){return false}var f=w.GetObject(),A=this.CountStat(),t=k%10,g=Math.floor(k/10)%10,m=Math.floor(k/100)%10,y=Math.floor(k/1000)%10,h=Math.floor(k/10000)%10,l=Math.floor(k/100000)%10,r=Math.floor(k/1000000)%10,C=Math.floor(k/10000000)%10,u=Math.floor(k/100000000)%10;if(t>0){f.AddText(this.histo.fName)}if(this.IsTProfile()){if(g>0){f.AddText("Entries = "+w.Format(A.entries,"entries"))}if(m>0){f.AddText("Mean = "+w.Format(A.meanx));f.AddText("Mean y = "+w.Format(A.meany))}if(y>0){f.AddText("Std Dev = "+w.Format(A.rmsx));f.AddText("Std Dev y = "+w.Format(A.rmsy))}}else{if(g>0){f.AddText("Entries = "+w.Format(A.entries,"entries"))}if(m>0){f.AddText("Mean = "+w.Format(A.meanx))}if(y>0){f.AddText("Std Dev = "+w.Format(A.rmsx))}if(h>0){var B=(this.histo.fArray.length>0)?this.histo.fArray[0]:0;f.AddText("Underflow = "+w.Format(B))}if(l>0){var B=(this.histo.fArray.length>0)?this.histo.fArray[this.histo.fArray.length-1]:0;f.AddText("Overflow = "+w.Format(B))}if(r>0){f.AddText("Integral = "+w.Format(A.integral,"entries"))}if(C>0){f.AddText("Skew = ")}if(u>0){f.AddText("Kurt = ")}}if(x!=0){var p=this.FindFunction("TF1");if(p!=null){var c=x%10;var q=Math.floor(x/10)%10;var d=Math.floor(x/100)%10;var j=Math.floor(x/1000)%10;if(d>0){f.AddText("#chi^2 / ndf = "+w.Format(p.fChisquare,"fit")+" / "+p.fNDF)}if(j>0){f.AddText("Prob = "+(("Math" in a)?w.Format(a.Math.Prob(p.fChisquare,p.fNDF)):""))}if(c>0){for(var o=0;o"}var s="";if(p.fParErrors!=null){s=w.Format(p.fParErrors[o],"last");if((Number(s)==0)&&(p.fParErrors[o]!=0)){s=w.Format(p.fParErrors[o],"4.2g")}}if((q>0)&&(s.length>0)){f.AddText(z+" = "+v+" #pm "+s)}else{f.AddText(z+" = "+v)}}}}}var i=f.fLines.arr.length,e=i*a.gStyle.StatFontSize;if((e<=0)||(a.gStyle.StatFont%10===3)){e=0.25*i*a.gStyle.StatH;f.fY1NDC=0.93-e;f.fY2NDC=0.93}return true};a.TH1Painter.prototype.DrawBars=function(){var o=this.frame_width(),m=this.frame_height();this.RecreateDrawG(false,"main_layer");var f=this.GetSelectIndex("x","left",-1),v=this.GetSelectIndex("x","right",1),j=this.main_painter(),u=this.root_pad(),g=this,q,s,r,h,d,k,e,l;var n="",t="",p="",c=this.options.Bar%10;if(c>4){c=4}for(q=f;q0){d=h+l;l=Math.round(l*c/10);if(j.swap_xy){t+="M0,"+h+"h"+e+"v"+l+"h"+(-e)+"z";p+="M0,"+d+"h"+e+"v"+(-l)+"h"+(-e)+"z"}else{t+="M"+h+","+e+"h"+l+"v"+(m-e)+"h"+(-l)+"z";p+="M"+d+","+e+"h"+(-l)+"v"+(m-e)+"h"+l+"z"}}}if(n.length>0){this.draw_g.append("svg:path").attr("d",n).call(this.fillatt.func)}if(t.length>0){this.draw_g.append("svg:path").attr("d",t).call(this.fillatt.func).style("fill",b.rgb(this.fillatt.color).brighter(0.5).toString())}if(p.length>0){this.draw_g.append("svg:path").attr("d",p).call(this.fillatt.func).style("fill",b.rgb(this.fillatt.color).darker(0.5).toString())}};a.TH1Painter.prototype.DrawBins=function(){this.CheckHistDrawAttributes();if(this.options.Bar>0){return this.DrawBars()}var c=this.frame_width(),d=this.frame_height();if(!this.draw_content||(c<=0)||(d<=0)){return this.RemoveDrawG()}this.RecreateDrawG(false,"main_layer");var g=this.GetSelectIndex("x","left",-1),N=this.GetSelectIndex("x","right",2),s=this.main_painter(),n=this.root_pad(),t=this,D="",H=false,e,k,j,K,C,J,B,l,M,E,F,Q,o,T=(this.options.Error!==10)&&(this.options.Mark!==10),f=(this.options.Error>0),v=(this.options.Mark>0),A=null,m=null,L=null,P="",O="",p=0,h,r,q,V,S,I,G,U="";if(f&&!v&&(this.histo.fMarkerStyle>1)){v=true}if(this.options.Error==12){if(this.fillatt.color=="none"){v=true}else{A=""}}else{if(this.options.Error>0){m=""}}if(v){if(!this.markeratt){this.markeratt=a.Painter.createAttMarker(this.histo)}if(this.markeratt.size>0){L="";this.markeratt.reset_pos()}else{v=false}}var z=((N-g)>3*c);if(this.options.Error==11){var u=this.lineatt.width+a.gStyle.EndErrorSize;P="m0,"+u+"v-"+2*u+"m0,"+u;O="m"+u+",0h-"+2*u+"m"+u+",0";p=Math.floor((this.lineatt.width-1)/2)}var R=f||v;if(R){z=true}for(Q=g;Q<=N;++Q){K=this.GetBinX(Q);if(this.logx&&(K<=0)){continue}C=Math.round(s.grx(K));H=(Q===N);if(H&&(g=-r)&&(h<=d+q)){if(A!==null){A+="M"+I+","+(h-r)+"h"+(G-I)+"v"+(r+q+1)+"h-"+(G-I)+"z"}if(m!==null){m+="M"+(I+p)+","+h+P+"h"+(G-I-2*p)+P+"M"+Math.round((I+G)/2)+","+(h-r+p)+O+"v"+(r+q-2*p)+O}if(L!==null){L+=this.markeratt.create((I+G)/2,h)}}}}if(!R&&((l!==M)||(E!==l))){if(F!==k){D+="h"+(k-F)}if(j===l){if(M!==E){D+="v"+(M-E)}if(l!==M){D+="v"+(l-M)}}else{if(l!==E){D+="v"+(l-E)}if(M!==l){D+="v"+(M-l)}if(j!==M){D+="v"+(j-M)}}F=k;E=j}if(H&&(F!==C)){D+="h"+(C-F)}o=Q;l=M=j=B;k=C}}else{if((B!==j)||H){if(C!==k){D+="h"+(C-k)}if(B!==j){D+="v"+(B-j)}j=B;k=C}}}}if((this.fillatt.color!=="none")&&(D.length>0)){var w=(d+3);if((this.hmin>=0)&&(s.gry(0)0)){this.draw_g.append("svg:path").attr("d",A).call(this.fillatt.func)}if((m!==null)&&(m.length>0)){this.draw_g.append("svg:path").attr("d",m).call(this.lineatt.func)}if((L!==null)&&(L.length>0)){this.draw_g.append("svg:path").attr("d",L).call(this.markeratt.func)}}else{if(D.length>0){this.draw_g.append("svg:path").attr("d",D).style("stroke-linejoin","miter").call(this.lineatt.func).call(this.fillatt.func)}}};a.TH1Painter.prototype.GetBinTips=function(i){var d=[],h=this.GetTipName(),e=this.main_painter();if(h.length>0){d.push(h)}var g=this.GetBinX(i),f=this.GetBinX(i+1),c=this.histo.getBinContent(i+1);if((this.options.Error>0)||(this.options.Mark>0)){d.push("x = "+e.AxisAsText("x",(g+f)/2));d.push("y = "+e.AxisAsText("y",c));if(this.options.Error>0){d.push("error x = "+((f-g)/2).toPrecision(4));d.push("error y = "+this.histo.getBinError(i+1).toPrecision(4))}}else{d.push("bin = "+(i+1));if(e.x_kind==="labels"){d.push("x = "+e.AxisAsText("x",g))}else{if(e.x_kind==="time"){d.push("x = "+e.AxisAsText("x",(g+f)/2))}else{d.push("x = ["+e.AxisAsText("x",g)+", "+e.AxisAsText("x",f)+")")}}if(c===Math.round(c)){d.push("entries = "+c)}else{d.push("entries = "+a.FFormat(c,a.gStyle.StatFormat))}}return d};a.TH1Painter.prototype.ProcessTooltip=function(J){if((J===null)||!this.draw_content||(this.options.Lego>0)){if(this.draw_g!==null){this.draw_g.select(".tooltip_bin").remove()}this.ProvideUserTooltip(null);return null}var y=this.frame_width(),u=this.frame_height(),o=this.main_painter(),E=this.root_pad(),I=this,x=null,G=true,h,C,e,s,B,q,g=this.GetSelectIndex("x","left",-1),F=this.GetSelectIndex("x","right",2),A=g,t=F;function k(m){var l=I.GetBinX(m);if((l<0)&&o.logx){return null}return o.grx(l)}function j(l){var m=I.histo.getBinContent(l+1);if(o.logy&&(mJ.x+0.5){t=z}else{A++;t--}}}x=t=A;h=k(x);while((A>g)&&(k(A-1)>h-1)){--A}while((tu/10){x=Math.round(A+(t-A)/u*J.y)}h=k(x)}h=Math.round(h);e=Math.round(k(x+1));if(this.options.Bar>0){var p=e-h;h+=Math.round(this.histo.fBarOffset/1000*p);e=h+Math.round(this.histo.fBarWidth/1000*p)}C=Math.round((h+e)/2);B=s=q=j(x);if((this.options.Error>0)||(this.options.Mark>0)){G=true;var D=3;if(this.markeratt){D=Math.max(D,2+Math.round(this.markeratt.size*4))}if(e-h<2*D){h=C-D;e=C+D}if(this.options.Error>0){var c=this.histo.getBinContent(x+1);var n=this.histo.getBinError(x+1);s=Math.round(o.gry(c+n));q=Math.round(o.gry(c-n));if((c==0)&&this.IsTProfile()){x=null}}s=Math.min(s,B-D);q=Math.max(q,B+D);if(!J.touch&&(J.nproc===1)){if((J.yq)){x=null}}}else{G=(J.nproc===1)&&(F-g=0)){q=Math.round(o.gry(0));if((q>u)||(q<=s)){q=u}}}}if(x!==null){if((x===g)&&(h>J.x+2)){x=null}else{if((x===F-1)&&(ee+2)){x=null}}}}var H=this.draw_g.select(".tooltip_bin");if((x===null)||((q<=0)||(s>=u))){H.remove();this.ProvideUserTooltip(null);return null}var K={x:C,y:B,color1:this.lineatt.color,color2:this.fillatt.color,lines:this.GetBinTips(x)};if(G){if(H.empty()){H=this.draw_g.append("svg:rect").attr("class","tooltip_bin h1bin").style("pointer-events","none")}K.changed=H.property("current_bin")!==x;if(K.changed){H.attr("x",h).attr("width",e-h).attr("y",s).attr("height",q-s).style("opacity","0.3").property("current_bin",x)}K.exact=(Math.abs(B-J.y)<=5)||((J.y>=s)&&(J.y<=q));K.menu=true;K.menu_dist=Math.sqrt((C-J.x)*(C-J.x)+(B-J.y)*(B-J.y))}else{var f=this.lineatt.width+3;if(H.empty()){H=this.draw_g.append("svg:circle").attr("class","tooltip_bin").style("pointer-events","none").attr("r",f).call(this.lineatt.func).call(this.fillatt.func)}K.exact=(Math.abs(C-J.x)<=f)&&(Math.abs(B-J.y)<=f);K.menu=K.exact;K.menu_dist=Math.sqrt((C-J.x)*(C-J.x)+(B-J.y)*(B-J.y));K.changed=H.property("current_bin")!==x;if(K.changed){H.attr("cx",C).attr("cy",B).property("current_bin",x)}}if(this.IsUserTooltipCallback()&&K.changed){this.ProvideUserTooltip({obj:this.histo,name:this.histo.fName,bin:x,cont:this.histo.getBinContent(x+1),grx:C,gry:B})}return K};a.TH1Painter.prototype.FillHistContextMenu=function(c){c.add("Auto zoom-in",this.AutoZoom);c.addDrawMenu("Draw with",["hist","p","e","e1","pe2","lego"],function(d){this.options=this.DecodeOptions(d);this.RedrawPad()})};a.TH1Painter.prototype.AutoZoom=function(){var f=this.GetSelectIndex("x","left",-1),d=this.GetSelectIndex("x","right",1),g=d-f;if(g==0){return}var c=this.histo.getBinContent(f+1);for(var e=f;e0){return}while((f1)){return true}if((e=="y")&&(Math.abs(c-d)>Math.abs(this.ymax-this.ymin)*0.000001)){return true}return false};a.TH1Painter.prototype.Draw2D=function(c){if(typeof this.Create3DScene==="function"){this.Create3DScene(-1)}if(typeof this.DrawColorPalette==="function"){this.DrawColorPalette(false)}this.DrawAxes();this.DrawGrids();this.DrawBins();this.DrawTitle();this.AddInteractive();a.CallBack(c)};a.TH1Painter.prototype.Draw3D=function(c){a.AssertPrerequisites("more2d;3d",function(){this.Create3DScene=a.Painter.HPainter_Create3DScene;this.Draw3D=a.Painter.TH1Painter_Draw3D;this.Draw3D(c)}.bind(this))};a.THistPainter.prototype.Get3DToolTip=function(d){var e={bin:d},c;switch(this.Dimension()){case 1:e.ix=d;e.iy=1;e.value=this.histo.getBinContent(e.ix);c=this.GetBinTips(d-1);break;case 2:e.ix=d%(this.nbinsx+2);e.iy=(d-e.ix)/(this.nbinsx+2);e.value=this.histo.getBinContent(e.ix,e.iy);c=this.GetBinTips(e.ix-1,e.iy-1);break;case 3:e.ix=d%(this.nbinsx+2);e.iy=((d-e.ix)/(this.nbinsx+2))%(this.nbinsy+2);e.iz=(d-e.ix-e.iy*(this.nbinsx+2))/(this.nbinsx+2)/(this.nbinsy+2);e.value=this.GetObject().getBinContent(e.ix,e.iy,e.iz);c=this.GetBinTips(e.ix-1,e.iy-1,e.iz-1);break}if(c){e.info=c[0];for(var f=1;f"+c[f]}}return e};a.TH1Painter.prototype.Redraw=function(d){this.CreateXY();var c=(this.options.Lego>0)?"Draw3D":"Draw2D";this[c](null,d)};a.Painter.drawHistogram1D=function(g,e,f){var d=new a.TH1Painter(e);d.SetDivId(g,1);d.options=d.DecodeOptions(f);d.CheckPadRange();d.ScanContent();d.CreateXY();if(a.gStyle.AutoStat&&d.create_canvas){d.CreateStat()}var c=(d.options.Lego>0)?"Draw3D":"Draw2D";d[c](function(){d.DrawNextFunction(0,function(){if(d.options.Lego===0){if(d.options.AutoZoom){d.AutoZoom()}}d.FillToolbar();d.DrawingReady()})});return d};a.Painter.drawText=function(e,d){var c=new a.TObjectPainter(d);c.SetDivId(e,2);c.Redraw=function(){var l=this.GetObject(),k=this.pad_width(),j=this.pad_height(),g=l.fX,o=l.fY,m=a.Painter.root_colors[l.fTextColor],i=true,f=0,n=1;if(l.TestBit(a.BIT(14))){g=g*k;o=(1-o)*j}else{if(this.main_painter()!==null){k=this.frame_width();j=this.frame_height();i=false;g=this.main_painter().grx(g);o=this.main_painter().gry(o)}else{if(this.root_pad()!==null){g=this.ConvertToNDC("x",g)*k;o=(1-this.ConvertToNDC("y",o))*j}else{l.fTextAlign=22;g=k/2;o=j/2;if(l.fTextSize===0){l.fTextSize=0.05}if(l.fTextColor===0){l.fTextColor=1}}}}this.RecreateDrawG(i,i?"text_layer":"upper_layer");if(l._typename=="TLatex"){f=1;n=0.9}else{if(l._typename=="TMathText"){f=2;n=0.8}}this.StartTextDrawing(l.fTextFont,Math.round(l.fTextSize*Math.min(k,j)*n));this.DrawText(l.fTextAlign,Math.round(g),Math.round(o),0,0,l.fTitle,m,f);this.FinishTextDrawing()};c.Redraw();return c.DrawingReady()};a.RawTextPainter=function(c){a.TBasePainter.call(this);this.txt=c;return this};a.RawTextPainter.prototype=Object.create(a.TBasePainter.prototype);a.RawTextPainter.prototype.RedrawObject=function(c){this.txt=c;this.Draw();return true};a.RawTextPainter.prototype.Draw=function(){var e=this.txt.value;if(e==null){e=""}var h="mathjax" in this.txt;if(!h&&!("as_is" in this.txt)){var d=e.split("\n");e="";for(var g=0;g"+d[g]+""}}var j=this.select_main();var c=j.select("div");if(c.empty()){c=j.append("div").style("max-width","100%").style("max-height","100%").style("overflow","auto")}c.html(e);this.SetDivId(this.divid);if(h){if(this["loading_mathjax"]){return}this["loading_mathjax"]=true;var f=this;a.AssertPrerequisites("mathjax",function(){f.loading_mathjax=false;if(typeof MathJax=="object"){MathJax.Hub.Queue(["Typeset",MathJax.Hub,j.node()])}})}};a.Painter.drawRawText=function(f,c,e){var d=new a.RawTextPainter(c);d.SetDivId(f);d.Draw();return d.DrawingReady()};a.Painter.FolderHierarchy=function(d,f){if((f==null)||!("fFolders" in f)||(f.fFolders==null)){return false}if(f.fFolders.arr.length===0){d._more=false;return true}d._childs=[];for(var c=0;c0?"ROOT.TBranch":"ROOT.TLeafF"};h._childs.push(d);if(c>0){d._childs=[];for(var e=0;e=0)){continue}var m={_parent:k,_name:l};if(e===null){m._value=m._title="null";if(!h){k._childs.push(m)}continue}var g=Object.prototype.toString.apply(e);var c=false;if((g.lastIndexOf("Array]")==g.length-6)&&(g.indexOf("[object")==0)){m._title=m._kind+" len="+e.length;c=(g!="[object Array]");if(e.length===0){m._value="[ ]";m._more=false}else{m._value="[...]";m._more=true;m._expand=a.Painter.ObjectHierarchy;m._obj=e}}else{if(typeof e=="object"){if("_typename" in e){m._kind=m._title="ROOT."+e._typename}var n=k,j=false;while(n&&!j){j=(n._obj===e);n=n._parent}if(j){m._value="{ prnt }";c=true}else{m._obj=e;m._value="{ }";if(e._typename=="TColor"){m._value=a.Painter.MakeColorRGB(e)}}}else{if((typeof e=="number")||(typeof e=="boolean")){c=true;if(l=="fBits"){m._value="0x"+e.toString(16)}else{m._value=e.toString()}m._vclass="h_value_num"}else{if(typeof e=="string"){c=true;m._value='"'+e+'"';m._vclass="h_value_str"}else{c=true;alert("miss "+l+" "+typeof e)}}}}if(!c||!h){k._childs.push(m)}}return true};a.hpainter=null;a.HierarchyPainter=function(c,d,e){a.TBasePainter.call(this);this.name=c;this.h=null;this.with_icons=true;this.background=e;this.files_monitoring=(d==null);this.nobrowser=d===null;if(!this.nobrowser){this.SetDivId(d)}if(a.hpainter==null){a.hpainter=this}};a.HierarchyPainter.prototype=Object.create(a.TBasePainter.prototype);a.HierarchyPainter.prototype.ToggleFloatBrowser=function(g){if(!this.nobrowser||!this.disp){return}var e=b.select("#"+this.disp.frameid);if(e.empty()){return}var d=b.select(e.node().parentNode);var c=d.select(".float_browser");if(c.empty()){if(g===false){return}var f=d.append("div").attr("class","jsroot");c=f.append("div").attr("class","float_browser").style("left","-320px");c.transition().delay(700).style("left","5px");this.SetDivId(c.node());this.RefreshHtml()}else{if(c.style("left")=="5px"){if(g!==true){c.transition().delay(700).style("left","-320px")}}else{if(g!==false){c.transition().delay(700).style("left","5px")}}}};a.HierarchyPainter.prototype.Cleanup=function(){this.clear(true)};a.HierarchyPainter.prototype.FileHierarchy=function(d){var c=this;var e={_name:d.fFileName,_kind:"ROOT.TFile",_file:d,_fullurl:d.fFullURL,_had_direct_read:false,_get:function(g,j,i){var f=this;if(g&&g._readobj){return a.CallBack(i,g,g._readobj)}if(g!=null){j=c.itemFullName(g,f)}function h(k){if(f._file==null){f._file=k}if(k==null){return a.CallBack(i,g,null)}k.ReadObject(j,function(n){if((g==null)&&(n!=null)){var o=c.Find({name:j,top:f,last_exists:true,check_keys:true});if((o!=null)&&("last" in o)&&(o.last!=f)){var l=k.GetDir(c.itemFullName(o.last,f));if(l){o.last._name=o.last._keyname;var m=c.itemFullName(o.last,f);a.Painter.KeysHierarchy(o.last,l.fKeys,k,m+"/")}}else{a.Painter.KeysHierarchy(f,k.fKeys,k,"")}g=c.Find({name:j,top:f})}if(g!=null){g._readobj=n;if("_expand" in g){g._name=g._keyname}}a.CallBack(i,g,n)})}if(f._file!=null){h(f._file)}else{new a.TFile(f._fullurl,h)}}};a.Painter.KeysHierarchy(e,d.fKeys,d,"");return e};a.HierarchyPainter.prototype.ForEach=function(e,d){if(d==null){d=this.h}if((d==null)||(typeof e!="function")){return}function c(f){e(f);if("_childs" in f){for(var g=0;g=0)&&(j0);return(c.last_exists&&l)?{last:l,rest:o}:null}var e=this.h;var f="";if(typeof c=="string"){f=c;c={}}else{if(typeof c=="object"){f=c.name;if("top" in c){e=c.top}}else{return null}}return d(e,f)};a.HierarchyPainter.prototype.itemFullName=function(d,e){var c="";while(d&&("_parent" in d)){if(c.length>0){c="/"+c}c=d._name+c;d=d._parent;if(e&&(d===e)){break}}return c};a.HierarchyPainter.prototype.ExecuteCommand=function(g,j){var k=this.Find(g);var c=g+"/cmd.json";var d=this;var f=b.select((typeof j=="function")?null:j);if("_numargs" in k){for(var e=0;e0){d+="/"}c.get({arg:d+g.rest,rest:g.rest},e,l)})}if((h!==null)&&(typeof h._obj=="object")){return a.CallBack(e,h,h._obj)}var k=h;while(k!=null){if(("_get" in k)&&(typeof k._get=="function")){return k._get(h,null,e,l)}k=("_parent" in k)?k._parent:null}a.CallBack(e,h,null)};a.HierarchyPainter.prototype.draw=function(e,d,c){return a.draw(e,d,c)};a.HierarchyPainter.prototype.redraw=function(e,d,c){return a.redraw(e,d,c)};a.HierarchyPainter.prototype.player=function(h,d,g){var e=this.Find(h);if(!e||!("_player" in e)){return a.CallBack(g,null)}var f=this;var c=("_prereq" in e)?e._prereq:"";a.AssertPrerequisites(c,function(){var i=a.findFunction(e._player);if(i==null){return a.CallBack(g,null)}f.CreateDisplay(function(k){var j=null;if(k){j=i(f,h,d)}a.CallBack(g,j)})})};a.HierarchyPainter.prototype.canDisplay=function(d,c){if(d==null){return false}if("_player" in d){return true}if(c=="inspect"){return true}var e=a.getDrawHandle(d._kind,c);return(e!=null)&&("func" in e)};a.HierarchyPainter.prototype.isItemDisplayed=function(d){var c=this.GetDisplay();if(!c){return false}return c.FindFrame(d)!==null};a.HierarchyPainter.prototype.display=function(g,k,d){var f=this,l=null,j=false,i=g,e="::_display_on_frame_::",c=k?k.indexOf(e):-1;if(c>=0){i=k.substr(c+e.length);k=k.substr(0,c)}function m(){if(l){l.SetItemName(g,j?null:k)}a.CallBack(d,l,g)}f.CreateDisplay(function(p){if(!p){return m()}var h=f.Find(g);if((h!=null)&&("_player" in h)){return f.player(g,k,m)}j=(typeof(k)=="string")&&(k.indexOf("update:")==0);if(j){k=k.substr(7);if((h==null)||("_doing_update" in h)){return m()}h._doing_update=true}if(h!=null){if(!f.canDisplay(h,k)){return m()}}var o="";if((typeof(k)=="string")&&(k.indexOf("divid:")>=0)){var n=k.indexOf("divid:");o=k.slice(n+6);k=k.slice(0,n)}a.progress("Loading "+g);f.get(g,function(q,r){a.progress();if(j&&q){delete q._doing_update}if(r==null){return m()}a.progress("Drawing "+g);if(o.length>0){l=j?f.redraw(o,r,k):f.draw(o,r,k)}else{p.ForEachPainter(function(t,u){if(t.GetItemName()!=g){return}if(!j&&(k!=null)&&(t.GetItemDrawOpt()!=k)){return}l=t;p.ActivateFrame(u);l.RedrawObject(r)})}if(l==null){if(j){a.console("something went wrong - did not found painter when doing update of "+g)}else{var s=p.FindFrame(i,true);b.select(s).html("");p.ActivateFrame(s);l=f.draw(b.select(s).attr("id"),r,k);q._painter=l;if(a.gStyle.DragAndDrop){f.enable_dropping(s,g)}}}a.progress();if(l===null){return m()}l.WhenReady(m)},k)})};a.HierarchyPainter.prototype.enable_dragging=function(c,d){};a.HierarchyPainter.prototype.enable_dropping=function(c,d){};a.HierarchyPainter.prototype.dropitem=function(f,e,d){var c=this;c.get(f,function(h,i){if(i!=null){var g=c.draw(e,i,"same");if(g){g.WhenReady(function(){g.SetItemName(f)})}}a.CallBack(d)});return true};a.HierarchyPainter.prototype.updateItems=function(c){if((this.disp==null)||(c==null)){return}var d=[],e=[];this.disp.ForEachPainter(function(f){var g=f.GetItemName();if((g==null)||(d.indexOf(g)>=0)){return}if(typeof c=="array"){if(c.indexOf(g)<0){return}}else{if(c!=g){return}}d.push(g);e.push("update:"+f.GetItemDrawOpt())},true);if(d.length>0){this.displayAll(d,e)}};a.HierarchyPainter.prototype.updateAll=function(e,f){if(this.disp==null){return}var h=[],d=[],g=this;this.disp.ForEachPainter(function(m){var n=m.GetItemName();var i=m.GetItemDrawOpt();if((n==null)||(h.indexOf(n)>=0)){return}var k=g.Find(n);if((k==null)||("_not_monitor" in k)||("_player" in k)){return}var j=false;if("_always_monitor" in k){j=true}else{var l=a.getDrawHandle(k._kind);if(l&&("monitor" in l)){if((l.monitor===false)||(l.monitor=="never")){return}if(l.monitor==="always"){j=true}}}if(j||!e){h.push(n);d.push("update:"+i)}},true);var c=this;if(this.files_monitoring&&!e){this.ForEachRootFile(function(i){c.ForEach(function(j){delete j._readobj},i);delete i._file})}if(h.length>0){this.displayAll(h,d)}};a.HierarchyPainter.prototype.displayAll=function(r,x,l){if((r==null)||(r.length==0)){return a.CallBack(l)}var q=this;if(!x){x=[]}while(x.lengthStart I/O test "+("IO" in a?"Mode="+a.IO.Mode:"")+"

    ");var e=new Date();return q.get(r[0],function(i,j){var h=new Date();b.select("#"+q.disp_frameid).append("h2").html("Item "+r[0]+" reading time = "+(h.getTime()-e.getTime())+"ms");return a.CallBack(l)})}var u=new Array(r.length);for(var p=0;p1)&&(v[0]=="'")&&(v[v.length-1]=="'")){r[p]=v.substr(1,v.length-2);w=false}var g=q.Find({name:r[p],check_keys:true});if(g){r[p]=q.itemFullName(g);continue}if(w&&(r[p].indexOf("+")>0)){u[p]=r[p].split("+");r[p]=u[p].shift();for(var o=0;o0)&&(q.Find(u[p][o])==null)){u[p][o]=u[p][o].substr(0,s)+r[p].substr(s)}}}var s=r[p].indexOf("_same_");if((s>0)&&!q.Find(r[p])&&(p>0)){r[p]=r[p].substr(0,s)+r[0].substr(s)}}for(var d=r.length-1;d>=0;--d){var t=q.Find(r[d]);if((t==null)||q.canDisplay(t,x[d])){continue}q.expand(r[d]);r.splice(d,1);x.splice(d,1);u.splice(d,1)}if(r.length==0){return a.CallBack(l)}var f=[];for(var d=0;d=0){c=r[d]+"_"+m++}f.push(c)}q.CreateDisplay(function(n){if(!n){return a.CallBack(l)}for(var j=0;j0)){return q.dropitem(u[A].shift(),i.divid,h.bind(this,A,i))}var z=false;for(var y=0;y=0;--j){c.UpdateTreeNode(i[j])}for(var j=0;j0){o+="/"}g(o+m.rest,m.now_found)})}k=m.last}if(k){var l=k._parent;while(l){if(!l._isopen){if(f){l._isopen=true;if(i.indexOf(l)<0){i.push(l)}}else{k=l;break}}l=l._parent}k._background="grey";if(h.indexOf(k)<0){h.push(k)}}g()}g()};a.HierarchyPainter.prototype.expand=function(h,e,g){var d=this,c=this.Find(h);if(!c&&g){return a.CallBack(e)}function f(j,l,i){if(!i){i=d.itemFullName(j)}if(l&&j&&(typeof j._expand==="function")){if(j._expand(j,l)){j._isopen=true;if(j._parent&&!j._parent._isopen){j._parent._isopen=true;d.UpdateTreeNode(j._parent)}else{d.UpdateTreeNode(j,g)}a.CallBack(e,j);return true}}if(!("_expand" in j)){var k=a.getDrawHandle(j._kind,"::expand");if(k&&("expand" in k)){a.AssertPrerequisites(k.prereq,function(){j._expand=a.findFunction(k.expand);if(!j._expand){delete j._expand}else{d.expand(i,e,g)}});return true}}if(l&&a.Painter.ObjectHierarchy(j,l)){j._isopen=true;if(j._parent&&!j._parent._isopen){j._parent._isopen=true;d.UpdateTreeNode(j._parent)}else{d.UpdateTreeNode(j,g)}a.CallBack(e,j);return true}return false}if(c){if(("_more" in c)&&!c._more){return a.CallBack(e)}if(f(c,c._obj,h)){return}}a.progress("Loading "+h);this.get(h,function(i,j){a.progress();if(j&&f(i,j)){return}a.CallBack(e)},"hierarchy_expand")};a.HierarchyPainter.prototype.GetTopOnlineItem=function(c){if(c!=null){while((c!=null)&&(!("_online" in c))){c=c._parent}return c}if(this.h==null){return null}if("_online" in this.h){return this.h}if((this.h._childs!=null)&&("_online" in this.h._childs[0])){return this.h._childs[0]}return null};a.HierarchyPainter.prototype.ForEachJsonFile=function(d){if(this.h==null){return}if("_jsonfile" in this.h){return a.CallBack(d,this.h)}if(this.h._childs!=null){for(var e=0;e0){d+="/"}d+=l;var n=a.NewHttpRequest(d,p,function(s){var r=null;if(!g&&(o!=null)&&("_after_request" in o)){r=a.findFunction(o._after_request)}else{if((f!=null)&&("after_request" in f)){r=f.after_request}}if(typeof r=="function"){var q=r(c,o,s,i,n);if((q!=null)&&(typeof q=="object")){s=q}}a.CallBack(m,o,s)});n.send(null)};a.Painter.OnlineHierarchy=function(c,d){if((d!=null)&&(c!=null)&&("_childs" in d)){for(var e=0;e3)&&((k[m].lastIndexOf(".js")==k[m].length-3)||(k[m].lastIndexOf(".css")==k[m].length-4))){if(h.indexOf(k[m])<0){h+=k[m]+";"}}else{if(j.indexOf(k[m])<0){j+=k[m]+";"}}}}});if(h.length>0){h="user:"+h}a.AssertPrerequisites(j+h,function(){c.ForEach(function(m){if(!("_drawfunc" in m)||!("_kind" in m)){return}var l="kind:"+m._kind;if(m._kind.indexOf("ROOT.")==0){l=m._kind.slice(5)}var k=m._drawopt;if(!a.canDraw(l)||(k!=null)){a.addDrawFunc({name:l,func:m._drawfunc,script:m._drawscript,opt:k})}});a.CallBack(f,c)})}if(!e){e=""}if(typeof e=="object"){var d=e;e="";return g(d)}a.NewHttpRequest(e+"h.json?compact=3","object",g).send(null)};a.HierarchyPainter.prototype.GetOnlineProp=function(e){var c=this.Find(e);if(c==null){return null}var d=c._name;while(c._parent!=null){c=c._parent;if("_online" in c){return{server:c._online,itemname:d}}d=c._name+"/"+d}return null};a.HierarchyPainter.prototype.FillOnlineMenu=function(d,k,i){var l=this;var e=this.Find(i);var c=a.getDrawOptions(e._kind,"nosame");var g=a.getDrawHandle(e._kind);var h=("_kind" in e)?e._kind.indexOf("ROOT.")==0:false;if(c!=null){d.addDrawMenu("Draw",c,function(m){l.display(i,m)})}if((e._childs==null)&&(e._more||h)){d.add("Expand",function(){l.expand(i)})}if(g&&("execute" in g)){d.add("Execute",function(){l.ExecuteCommand(i,d.tree_node)})}var j=k.server+k.itemname+"/draw.htm";var f="?";if(this.IsMonitoring()){j+=f+"monitoring="+this.MonitoringInterval();f="&"}if(c!=null){d.addDrawMenu("Draw in new window",c,function(m){window.open(j+f+"opt="+m)})}if((c!=null)&&(c.length>0)&&h){d.addDrawMenu("Draw as png",c,function(m){window.open(k.server+k.itemname+"/root.png?w=400&h=300&opt="+m)})}if("_player" in e){d.add("Player",function(){l.player(i)})}};a.HierarchyPainter.prototype.Adopt=function(c){this.h=c;this.RefreshHtml()};a.HierarchyPainter.prototype.SetMonitoring=function(c){this._monitoring_on=false;this._monitoring_interval=3000;c=(c===undefined)?0:parseInt(c);if(!isNaN(c)&&(c>0)){this._monitoring_on=true;this._monitoring_interval=Math.max(100,c)}};a.HierarchyPainter.prototype.MonitoringInterval=function(c){return("_monitoring_interval" in this)?this._monitoring_interval:3000};a.HierarchyPainter.prototype.EnableMonitoring=function(c){this._monitoring_on=c};a.HierarchyPainter.prototype.IsMonitoring=function(){return this._monitoring_on};a.HierarchyPainter.prototype.SetDisplay=function(d,c){if((c==null)&&(typeof d=="object")){this.disp=d;this.disp_kind="custom";this.disp_frameid=null}else{this.disp_kind=d;this.disp_frameid=c}};a.HierarchyPainter.prototype.GetLayout=function(){return this.disp_kind};a.HierarchyPainter.prototype.clear=function(c){if(this.disp){this.disp.Reset();delete this.disp}this.ForEach(function(d){delete d._painter;if(!c&&(typeof d.clear=="function")){d.clear()}});if(c){this.select_main().html("");delete this.h}};a.HierarchyPainter.prototype.GetDisplay=function(){return("disp" in this)?this.disp:null};a.HierarchyPainter.prototype.CreateDisplay=function(d){var c=this;if("disp" in this){if((c.disp.NumDraw()>0)||(c.disp_kind=="custom")){return a.CallBack(d,c.disp)}c.disp.Reset();delete c.disp}if(document.getElementById(this.disp_frameid)==null){return a.CallBack(d,null)}if(c.disp_kind=="simple"){c.disp=new a.SimpleDisplay(c.disp_frameid)}else{if(c.disp_kind.search("grid")==0){c.disp=new a.GridDisplay(c.disp_frameid,c.disp_kind)}else{return a.AssertPrerequisites("jq2d",function(){c.CreateDisplay(d)})}}a.CallBack(d,c.disp)};a.HierarchyPainter.prototype.updateOnOtherFrames=function(c,e){var f=this.disp;if(f==null){return false}var d=false;f.ForEachPainter(function(g,h){if((g===c)||(g.GetItemName()!=c.GetItemName())){return}f.ActivateFrame(h);g.RedrawObject(e);d=true});return d};a.HierarchyPainter.prototype.CheckResize=function(c){if("disp" in this){this.disp.CheckMDIResize(null,c)}};a.HierarchyPainter.prototype.StartGUI=function(n,h){var g=this,j=a.GetUrlOptionAsArray("file;files"),q=a.GetUrlOptionAsArray("json"),f=a.GetUrlOption("path"),o=a.GetUrlOptionAsArray("expand");if(o.length==0&&(a.GetUrlOption("expand")=="")){o.push("")}if(f!=null){for(var k=0;k0)){this.disp_kind=l}else{switch(c.length){case 0:case 1:this.disp_kind="simple";break;case 2:this.disp_kind="grid 1x2";break;default:this.disp_kind="flex"}}}if(a.GetUrlOption("files_monitoring")!=null){this.files_monitoring=true}this.SetMonitoring(p);function m(){if(q.length>0){g.OpenJsonFile(q.shift(),m)}else{if(j.length>0){g.OpenRootFile(j.shift(),m)}else{if(o.length>0){g.expand(o.shift(),m)}else{g.displayAll(c,e,function(){g.RefreshHtml();a.RegisterForResize(g);if(n||g.GetTopOnlineItem()||g.IsMonitoring()){setInterval(function(){g.updateAll(!g.IsMonitoring())},g.MonitoringInterval())}a.CallBack(h)})}}}}function d(){if(("_monitoring" in g.h)&&(p==null)){g.SetMonitoring(g.h._monitoring)}if(("_layout" in g.h)&&(l==null)){g.disp_kind=g.h._layout}if(("_loadfile" in g.h)&&(j.length==0)){j=a.ParseAsArray(g.h._loadfile)}if(("_drawitem" in g.h)&&(c.length==0)){c=a.ParseAsArray(g.h._drawitem);e=a.ParseAsArray(g.h._drawopt)}m()}if(n){g.OpenOnline(n,d)}else{m()}};a.BuildNobrowserGUI=function(){var c=b.select("#simpleGUI");var d=false,e=false;if(c.empty()){d=true;c=b.select("#onlineGUI");if(c.empty()){c=b.select("#drawGUI");e=true}if(c.empty()){return alert("no div for simple nobrowser gui found")}}a.Painter.readStyleFromURL();b.select("html").style("height","100%");b.select("body").style({"min-height":"100%",margin:"0px",overflow:"hidden"});c.style({position:"absolute",left:"1px",top:"1px",bottom:"1px",right:"1px"});var h=new a.HierarchyPainter("root",null);h.SetDisplay(a.GetUrlOption("layout",null,"simple"),c.attr("id"));var f=null;if(d){var g=a.findFunction("GetCachedHierarchy");if(typeof g=="function"){f=g()}if(typeof f!="object"){f=""}}h.StartGUI(f,function(){if(!e){return}var j=a.findFunction("GetCachedObject");var k=(typeof j=="function")?a.JSONR_unref(j()):null;if(k!=null){h._cached_draw_object=k}var i=a.GetUrlOption("opt");h.display("",i,function(l){if(a.GetUrlOption("websocket")!==null){l.OpenWebsocket()}})})};a.Painter.drawStreamerInfo=function(h,g){var j=new a.HierarchyPainter("sinfo",h,"white");j.h={_name:"StreamerInfo",_childs:[]};for(var f=0;f0)){c.h._name=d.fName}c.select_main().style("overflow","auto");a.Painter.ObjectHierarchy(c.h,d);c.RefreshHtml(function(){c.SetDivId(e);c.DrawingReady()});return c};a.MDIDisplay=function(c){this.frameid=c;b.select("#"+this.frameid).property("mdi",this)};a.MDIDisplay.prototype.ForEachFrame=function(c,d){console.warn("ForEachFrame not implemented in MDIDisplay")};a.MDIDisplay.prototype.ForEachPainter=function(c,d){this.ForEachFrame(function(f){var e=new a.TObjectPainter();e.SetDivId(b.select(f).attr("id"),-1);e.ForEachPainter(function(g){c(g,f)})},d)};a.MDIDisplay.prototype.NumDraw=function(){var c=0;this.ForEachFrame(function(){++c});return c};a.MDIDisplay.prototype.FindFrame=function(d,e){var c=null;this.ForEachFrame(function(f){if(b.select(f).attr("frame_title")==d){c=f}});if((c==null)&&e){c=this.CreateFrame(d)}return c};a.MDIDisplay.prototype.ActivateFrame=function(c){};a.MDIDisplay.prototype.CheckMDIResize=function(d,e){var c=null;this.ForEachPainter(function(f,g){if((d!==null)&&(b.select(g).attr("id")!=d)){return}if((f.GetItemName()!==null)&&(typeof f.CheckResize=="function")){if(c===g){return}f.CheckResize(e);c=g}})};a.MDIDisplay.prototype.Reset=function(){this.ForEachFrame(function(c){a.cleanup(c)});b.select("#"+this.frameid).html("").property("mdi",null)};a.MDIDisplay.prototype.Draw=function(f,d,c){if(!d){return}if(!a.canDraw(d._typename,c)){return}var e=this.FindFrame(f,true);this.ActivateFrame(e);return a.redraw(b.select(e).attr("id"),d,c)};a.CustomDisplay=function(){a.MDIDisplay.call(this,"dummy");this.frames={}};a.CustomDisplay.prototype=Object.create(a.MDIDisplay.prototype);a.CustomDisplay.prototype.AddFrame=function(d,c){if(!(d in this.frames)){this.frames[d]=""}this.frames[d]+=(c+";")};a.CustomDisplay.prototype.ForEachFrame=function(d,g){var f=Object.keys(this.frames);for(var c=0;c=0){return b.select("#"+f[d]).node()}}return null};a.CustomDisplay.prototype.Reset=function(){a.MDIDisplay.prototype.Reset.call(this);this.ForEachFrame(function(c){b.select(c).html("")})};a.SimpleDisplay=function(c){a.MDIDisplay.call(this,c)};a.SimpleDisplay.prototype=Object.create(a.MDIDisplay.prototype);a.SimpleDisplay.prototype.ForEachFrame=function(c,e){var d=b.select("#"+this.frameid+"_simple_display");if(!d.empty()){a.CallBack(c,d.node())}};a.SimpleDisplay.prototype.CreateFrame=function(c){a.cleanup(this.frameid+"_simple_display");return b.select("#"+this.frameid).html("").append("div").attr("id",this.frameid+"_simple_display").style("width","100%").style("height","100%").style("overflow","hidden").attr("frame_title",c).node()};a.SimpleDisplay.prototype.Reset=function(){a.MDIDisplay.prototype.Reset.call(this);b.select("#"+this.frameid).html("")};a.GridDisplay=function(e,d,c){a.MDIDisplay.call(this,e);this.cnt=0;if(typeof d=="string"){if(d.search("grid")==0){d=d.slice(4).trim()}var f=d.search("x");if(f>0){c=parseInt(d.slice(f+1));d=parseInt(d.slice(0,f))}else{d=parseInt(d);c=d}if(isNaN(d)){d=3}if(isNaN(c)){c=3}}if(!d){d=3}if(!c){c=d}this.sizex=d;this.sizey=c};a.GridDisplay.prototype=Object.create(a.MDIDisplay.prototype);a.GridDisplay.prototype.NumGridFrames=function(){return this.sizex*this.sizey};a.GridDisplay.prototype.IsSingle=function(){return(this.sizex==1)&&(this.sizey==1)};a.GridDisplay.prototype.ForEachFrame=function(c,f){for(var d=0;d";var c=0;for(var f=0;f";for(var e=0;e
    "}m+=""}m+="";d.html(m);d.selectAll(".grid_cell").style({width:p+"px",height:l+"px",overflow:"hidden"})}k=g+"_"+this.cnt;if(++this.cnt>=this.sizex*this.sizey){this.cnt=0}}a.cleanup(k);return b.select("#"+k).html("").attr("frame_title",o).node()};a.GridDisplay.prototype.Reset=function(){a.MDIDisplay.prototype.Reset.call(this);if(this.IsSingle()){b.select("#"+this.frameid).attr("frame_title",null)}this.cnt=0};a.GridDisplay.prototype.CheckMDIResize=function(g,e){if(!this.IsSingle()){var c=b.select("#"+this.frameid);var i=c.node().getBoundingClientRect();var f=Math.floor(i.height/this.sizey)-1;var d=Math.floor(i.width/this.sizex)-1;c.selectAll(".grid_cell").style({width:d+"px",height:f+"px"})}a.MDIDisplay.prototype.CheckMDIResize.call(this,g,e)};a.RegisterForResize=function(f,d){if((f===null)||(f===undefined)){return}var g=null,c=d?d:300;if(c<20){c=20}function e(){g=null;document.body.style.cursor="wait";if(typeof f=="function"){f()}else{if((typeof f=="object")&&(typeof f.CheckResize=="function")){f.CheckResize()}else{if(typeof f=="string"){var i=b.select("#"+f);if(!i.empty()){var j=i.property("mdi");if(j){j.CheckMDIResize()}else{a.resize(i.node())}}}}}document.body.style.cursor="auto"}function h(){if(g!==null){clearTimeout(g)}g=setTimeout(e,c)}window.addEventListener("resize",h)};a.addDrawFunc({name:"TCanvas",icon:"img_canvas",func:a.Painter.drawCanvas});a.addDrawFunc({name:"TPad",icon:"img_canvas",func:a.Painter.drawPad});a.addDrawFunc({name:"TSlider",icon:"img_canvas",func:a.Painter.drawPad});a.addDrawFunc({name:"TFrame",icon:"img_frame",func:a.Painter.drawFrame});a.addDrawFunc({name:"TPaveText",icon:"img_pavetext",func:a.Painter.drawPaveText});a.addDrawFunc({name:"TPaveStats",icon:"img_pavetext",func:a.Painter.drawPaveText});a.addDrawFunc({name:"TPaveLabel",icon:"img_pavelabel",func:a.Painter.drawPaveText});a.addDrawFunc({name:"TLatex",icon:"img_text",func:a.Painter.drawText});a.addDrawFunc({name:"TMathText",icon:"img_text",func:a.Painter.drawText});a.addDrawFunc({name:"TText",icon:"img_text",func:a.Painter.drawText});a.addDrawFunc({name:/^TH1/,icon:"img_histo1d",func:a.Painter.drawHistogram1D,opt:";hist;P;P0;E;E1;E2;same"});a.addDrawFunc({name:"TProfile",icon:"img_profile",func:a.Painter.drawHistogram1D,opt:";E0;E1;E2;p;hist"});a.addDrawFunc({name:"TH2Poly",icon:"img_histo2d"});a.addDrawFunc({name:/^TH2/,icon:"img_histo2d",prereq:"more2d",func:"JSROOT.Painter.drawHistogram2D",opt:";COL;COLZ;COL0Z;BOX;SCAT;TEXT;LEGO;LEGO0;LEGO1;LEGO2;LEGO3;LEGO4;same"});a.addDrawFunc({name:/^TH3/,icon:"img_histo3d",prereq:"3d",func:"JSROOT.Painter.drawHistogram3D"});a.addDrawFunc({name:"THStack",prereq:"more2d",func:"JSROOT.Painter.drawHStack"});a.addDrawFunc({name:"TPolyMarker3D",icon:"img_histo3d",prereq:"3d",func:"JSROOT.Painter.drawPolyMarker3D"});a.addDrawFunc({name:"TGraphPolargram"});a.addDrawFunc({name:/^TGraph/,icon:"img_graph",prereq:"more2d",func:"JSROOT.Painter.drawGraph",opt:";L;P"});a.addDrawFunc({name:"TCutG",icon:"img_graph",prereq:"more2d",func:"JSROOT.Painter.drawGraph",opt:";L;P"});a.addDrawFunc({name:/^RooHist/,icon:"img_graph",prereq:"more2d",func:"JSROOT.Painter.drawGraph",opt:";L;P"});a.addDrawFunc({name:/^RooCurve/,icon:"img_graph",prereq:"more2d",func:"JSROOT.Painter.drawGraph",opt:";L;P"});a.addDrawFunc({name:"TMultiGraph",icon:"img_mgraph",prereq:"more2d",func:"JSROOT.Painter.drawMultiGraph"});a.addDrawFunc({name:"TStreamerInfoList",icon:"img_question",func:a.Painter.drawStreamerInfo});a.addDrawFunc({name:"TPaletteAxis",icon:"img_colz",prereq:"more2d",func:"JSROOT.Painter.drawPaletteAxis"});a.addDrawFunc({name:"kind:Text",icon:"img_text",func:a.Painter.drawRawText});a.addDrawFunc({name:"TF1",icon:"img_graph",prereq:"math;more2d",func:"JSROOT.Painter.drawFunction"});a.addDrawFunc({name:"TEllipse",icon:"img_graph",prereq:"more2d",func:"JSROOT.Painter.drawEllipse"});a.addDrawFunc({name:"TLine",icon:"img_graph",prereq:"more2d",func:"JSROOT.Painter.drawLine"});a.addDrawFunc({name:"TArrow",icon:"img_graph",prereq:"more2d",func:"JSROOT.Painter.drawArrow"});a.addDrawFunc({name:"TGaxis",icon:"img_graph",func:a.drawGaxis});a.addDrawFunc({name:"TLegend",icon:"img_pavelabel",prereq:"more2d",func:"JSROOT.Painter.drawLegend"});a.addDrawFunc({name:"TBox",icon:"img_graph",prereq:"more2d",func:"JSROOT.Painter.drawBox"});a.addDrawFunc({name:"TWbox",icon:"img_graph",prereq:"more2d",func:"JSROOT.Painter.drawBox"});a.addDrawFunc({name:"TSliderBox",icon:"img_graph",prereq:"more2d",func:"JSROOT.Painter.drawBox"});a.addDrawFunc({name:"TGeoVolume",icon:"img_histo3d",prereq:"geom",func:"JSROOT.Painter.drawGeoObject",expand:"JSROOT.GEO.expandObject",opt:";more;all;count"});a.addDrawFunc({name:"TEveGeoShapeExtract",icon:"img_histo3d",prereq:"geom",func:"JSROOT.Painter.drawGeoObject",expand:"JSROOT.GEO.expandObject",opt:";more;all;count"});a.addDrawFunc({name:"TGeoManager",icon:"img_histo3d",prereq:"geom",expand:"JSROOT.GEO.expandObject",func:"JSROOT.Painter.drawGeoObject",opt:";more;all;count",dflt:"expand"});a.addDrawFunc({name:/^TGeo/,icon:"img_histo3d",prereq:"geom",func:"JSROOT.Painter.drawGeoObject",opt:";more;all;axis;compa;count"});a.addDrawFunc({name:"kind:Command",icon:"img_execute",execute:true});a.addDrawFunc({name:"TFolder",icon:"img_folder",icon2:"img_folderopen",noinspect:true,expand:a.Painter.FolderHierarchy});a.addDrawFunc({name:"TTask",icon:"img_task",expand:a.Painter.TaskHierarchy,for_derived:true});a.addDrawFunc({name:"TTree",icon:"img_tree",noinspect:true,expand:a.Painter.TreeHierarchy});a.addDrawFunc({name:"TNtuple",icon:"img_tree",noinspect:true,expand:a.Painter.TreeHierarchy});a.addDrawFunc({name:"TBranch",icon:"img_branch",noinspect:true});a.addDrawFunc({name:/^TLeaf/,icon:"img_leaf",noinspect:true});a.addDrawFunc({name:"TList",icon:"img_list",noinspect:true,expand:a.Painter.ListHierarchy});a.addDrawFunc({name:"TObjArray",icon:"img_list",noinspect:true,expand:a.Painter.ListHierarchy});a.addDrawFunc({name:"TClonesArray",icon:"img_list",noinspect:true,expand:a.Painter.ListHierarchy});a.addDrawFunc({name:"TColor",icon:"img_color"});a.addDrawFunc({name:"TFile",icon:"img_file",noinspect:true});a.addDrawFunc({name:"TMemFile",icon:"img_file",noinspect:true});a.addDrawFunc({name:"Session",icon:"img_globe"});a.addDrawFunc({name:"kind:TopFolder",icon:"img_base"});a.addDrawFunc({name:"kind:Folder",icon:"img_folder",icon2:"img_folderopen",noinspect:true});a.getDrawHandle=function(e,f){if(typeof e!="string"){return null}if(f===""){f=null}var l=null;if((f===null)&&(e in a.DrawFuncs.cache)){return a.DrawFuncs.cache[e]}var n=(e.indexOf("ROOT.")==0)?e.substr(5):"kind:"+e;var d=0;for(var k=0;k=0){return m}}}}else{if(f===d){return m}}}++d}return l};a.addStreamerInfos=function(d){if(d===null){return}function c(n,m){if(n.fElements==null){return null}if(m>10){return null}for(var l=0;l0){if(h.painter_kind===undefined){h.painter_kind=(f.indexOf("JSROOT.Painter")==0)?"object":"base"}j=(h.painter_kind=="base")?new a.TBasePainter():new a.TObjectPainter(g);a.AssertPrerequisites(k,function(){var l=a.findFunction(f);if(!l){alert("Fail to find function "+f+" after loading "+k)}else{h.func=l;if(c()!==j){alert("Painter function "+f+" do not follow rules of dynamicaly loaded painters")}}});return j}var e=a.findFunction(f);if(e){h.func=e;return c()}return null};a.redraw=function(j,h,f){if(h==null){return}var g=new a.TObjectPainter();g.SetDivId(j,-1);var d=g.pad_painter();if(d!==null){if(h._typename==="TCanvas"){d.RedrawObject(h);return d}for(var e=0;e 1) t -= 1; + if (t < 1 / 6) return p + (q - p) * 6 * t; + if (t < 1 / 2) return q; + if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; + return p; + } + var q = l < 0.5 ? l * (1 + s) : l + s - l * s; + var p = 2 * l - q; + r = hue2rgb(p, q, h + 1 / 3); + g = hue2rgb(p, q, h); + b = hue2rgb(p, q, h - 1 / 3); + } + return 'rgb(' + Math.round(r * 255) + ',' + Math.round(g * 255) + ',' + Math.round(b * 255) + ')'; + } + + var palette = [], saturation = 1, lightness = 0.5, maxHue = 280, minHue = 0, maxPretty = 50; + for (var i = 0; i < maxPretty; ++i) { + var hue = (maxHue - (i + 1) * ((maxHue - minHue) / maxPretty)) / 360.0; + var rgbval = HLStoRGB(hue, lightness, saturation); + palette.push(rgbval); + } + return palette; + } + + JSROOT.Painter.CreateGrayPalette = function() { + var palette = []; + for (var i = 0; i < 50; ++i) { + var code = Math.round((i+2)/60 * 255 ); + palette.push('rgb('+code+','+code+','+code+')'); + } + return palette; + } + + JSROOT.Painter.CreateGradientColorTable = function(Stops, Red, Green, Blue, NColors, alpha) { + // skip all checks + var palette = []; + + for (var g = 1; g < Stops.length; g++) { + // create the colors... + var nColorsGradient = parseInt(Math.floor(NColors*Stops[g]) - Math.floor(NColors*Stops[g-1])); + for (var c = 0; c < nColorsGradient; c++) { + var col = Math.round(Red[g-1] + c * (Red[g] - Red[g-1])/nColorsGradient) + "," + + Math.round(Green[g-1] + c * (Green[g] - Green[g-1])/ nColorsGradient) + "," + + Math.round(Blue[g-1] + c * (Blue[g] - Blue[g-1])/ nColorsGradient); + palette.push("rgb("+col+")"); + } + } + + return palette; + } + + JSROOT.Painter.GetColorPalette = function(col,alfa) { + if ((col===null) || (col===0)) col = JSROOT.gStyle.Palette; + if ((col>0) && (col<10)) return JSROOT.Painter.CreateGrayPalette(); + if (col < 51) return JSROOT.Painter.CreateDefaultPalette(); + if (col > 112) col = 57; + var red, green, blue, + stops = [ 0.0000, 0.1250, 0.2500, 0.3750, 0.5000, 0.6250, 0.7500, 0.8750, 1.0000 ]; + switch(col) { + + // Deep Sea + case 51: + red = [ 0, 9, 13, 17, 24, 32, 27, 25, 29]; + green = [ 0, 0, 0, 2, 37, 74, 113, 160, 221]; + blue = [ 28, 42, 59, 78, 98, 129, 154, 184, 221]; + break; + + // Grey Scale + case 52: + red = [ 0, 32, 64, 96, 128, 160, 192, 224, 255]; + green = [ 0, 32, 64, 96, 128, 160, 192, 224, 255]; + blue = [ 0, 32, 64, 96, 128, 160, 192, 224, 255]; + break; + + // Dark Body Radiator + case 53: + red = [ 0, 45, 99, 156, 212, 230, 237, 234, 242]; + green = [ 0, 0, 0, 45, 101, 168, 238, 238, 243]; + blue = [ 0, 1, 1, 3, 9, 8, 11, 95, 230]; + break; + + // Two-color hue (dark blue through neutral gray to bright yellow) + case 54: + red = [ 0, 22, 44, 68, 93, 124, 160, 192, 237]; + green = [ 0, 16, 41, 67, 93, 125, 162, 194, 241]; + blue = [ 97, 100, 99, 99, 93, 68, 44, 26, 74]; + break; + + // Rain Bow + case 55: + red = [ 0, 5, 15, 35, 102, 196, 208, 199, 110]; + green = [ 0, 48, 124, 192, 206, 226, 97, 16, 0]; + blue = [ 99, 142, 198, 201, 90, 22, 13, 8, 2]; + break; + + // Inverted Dark Body Radiator + case 56: + red = [ 242, 234, 237, 230, 212, 156, 99, 45, 0]; + green = [ 243, 238, 238, 168, 101, 45, 0, 0, 0]; + blue = [ 230, 95, 11, 8, 9, 3, 1, 1, 0]; + break; + + // Bird + case 57: + red = [ 0.2082*255, 0.0592*255, 0.0780*255, 0.0232*255, 0.1802*255, 0.5301*255, 0.8186*255, 0.9956*255, 0.9764*255]; + green = [ 0.1664*255, 0.3599*255, 0.5041*255, 0.6419*255, 0.7178*255, 0.7492*255, 0.7328*255, 0.7862*255, 0.9832*255]; + blue = [ 0.5293*255, 0.8684*255, 0.8385*255, 0.7914*255, 0.6425*255, 0.4662*255, 0.3499*255, 0.1968*255, 0.0539*255]; + break; + + // Cubehelix + case 58: + red = [ 0.0000, 0.0956*255, 0.0098*255, 0.2124*255, 0.6905*255, 0.9242*255, 0.7914*255, 0.7596*255, 1.0000*255]; + green = [ 0.0000, 0.1147*255, 0.3616*255, 0.5041*255, 0.4577*255, 0.4691*255, 0.6905*255, 0.9237*255, 1.0000*255]; + blue = [ 0.0000, 0.2669*255, 0.3121*255, 0.1318*255, 0.2236*255, 0.6741*255, 0.9882*255, 0.9593*255, 1.0000*255]; + break; + + // Green Red Violet + case 59: + red = [13, 23, 25, 63, 76, 104, 137, 161, 206]; + green = [95, 67, 37, 21, 0, 12, 35, 52, 79]; + blue = [ 4, 3, 2, 6, 11, 22, 49, 98, 208]; + break; + + // Blue Red Yellow + case 60: + red = [0, 61, 89, 122, 143, 160, 185, 204, 231]; + green = [0, 0, 0, 0, 14, 37, 72, 132, 235]; + blue = [0, 140, 224, 144, 4, 5, 6, 9, 13]; + break; + + // Ocean + case 61: + red = [ 14, 7, 2, 0, 5, 11, 55, 131, 229]; + green = [105, 56, 26, 1, 42, 74, 131, 171, 229]; + blue = [ 2, 21, 35, 60, 92, 113, 160, 185, 229]; + break; + + // Color Printable On Grey + case 62: + red = [ 0, 0, 0, 70, 148, 231, 235, 237, 244]; + green = [ 0, 0, 0, 0, 0, 69, 67, 216, 244]; + blue = [ 0, 102, 228, 231, 177, 124, 137, 20, 244]; + break; + + // Alpine + case 63: + red = [ 50, 56, 63, 68, 93, 121, 165, 192, 241]; + green = [ 66, 81, 91, 96, 111, 128, 155, 189, 241]; + blue = [ 97, 91, 75, 65, 77, 103, 143, 167, 217]; + break; + + // Aquamarine + case 64: + red = [ 145, 166, 167, 156, 131, 114, 101, 112, 132]; + green = [ 158, 178, 179, 181, 163, 154, 144, 152, 159]; + blue = [ 190, 199, 201, 192, 176, 169, 160, 166, 190]; + break; + + // Army + case 65: + red = [ 93, 91, 99, 108, 130, 125, 132, 155, 174]; + green = [ 126, 124, 128, 129, 131, 121, 119, 153, 173]; + blue = [ 103, 94, 87, 85, 80, 85, 107, 120, 146]; + break; + + // Atlantic + case 66: + red = [ 24, 40, 69, 90, 104, 114, 120, 132, 103]; + green = [ 29, 52, 94, 127, 150, 162, 159, 151, 101]; + blue = [ 29, 52, 96, 132, 162, 181, 184, 186, 131]; + break; + + // Aurora + case 67: + red = [ 46, 38, 61, 92, 113, 121, 132, 150, 191]; + green = [ 46, 36, 40, 69, 110, 135, 131, 92, 34]; + blue = [ 46, 80, 74, 70, 81, 105, 165, 211, 225]; + break; + + // Avocado + case 68: + red = [ 0, 4, 12, 30, 52, 101, 142, 190, 237]; + green = [ 0, 40, 86, 121, 140, 172, 187, 213, 240]; + blue = [ 0, 9, 14, 18, 21, 23, 27, 35, 101]; + break; + + // Beach + case 69: + red = [ 198, 206, 206, 211, 198, 181, 161, 171, 244]; + green = [ 103, 133, 150, 172, 178, 174, 163, 175, 244]; + blue = [ 49, 54, 55, 66, 91, 130, 184, 224, 244]; + break; + + // Black Body + case 70: + red = [ 243, 243, 240, 240, 241, 239, 186, 151, 129]; + green = [ 0, 46, 99, 149, 194, 220, 183, 166, 147]; + blue = [ 6, 8, 36, 91, 169, 235, 246, 240, 233]; + break; + + // Blue Green Yellow + case 71: + red = [ 22, 19, 19, 25, 35, 53, 88, 139, 210]; + green = [ 0, 32, 69, 108, 135, 159, 183, 198, 215]; + blue = [ 77, 96, 110, 116, 110, 100, 90, 78, 70]; + break; + + // Brown Cyan + case 72: + red = [ 68, 116, 165, 182, 189, 180, 145, 111, 71]; + green = [ 37, 82, 135, 178, 204, 225, 221, 202, 147]; + blue = [ 16, 55, 105, 147, 196, 226, 232, 224, 178]; + break; + + // CMYK + case 73: + red = [ 61, 99, 136, 181, 213, 225, 198, 136, 24]; + green = [ 149, 140, 96, 83, 132, 178, 190, 135, 22]; + blue = [ 214, 203, 168, 135, 110, 100, 111, 113, 22]; + break; + + // Candy + case 74: + red = [ 76, 120, 156, 183, 197, 180, 162, 154, 140]; + green = [ 34, 35, 42, 69, 102, 137, 164, 188, 197]; + blue = [ 64, 69, 78, 105, 142, 177, 205, 217, 198]; + break; + + // Cherry + case 75: + red = [ 37, 102, 157, 188, 196, 214, 223, 235, 251]; + green = [ 37, 29, 25, 37, 67, 91, 132, 185, 251]; + blue = [ 37, 32, 33, 45, 66, 98, 137, 187, 251]; + break; + + // Coffee + case 76: + red = [ 79, 100, 119, 137, 153, 172, 192, 205, 250]; + green = [ 63, 79, 93, 103, 115, 135, 167, 196, 250]; + blue = [ 51, 59, 66, 61, 62, 70, 110, 160, 250]; + break; + + // Dark Rain Bow + case 77: + red = [ 43, 44, 50, 66, 125, 172, 178, 155, 157]; + green = [ 63, 63, 85, 101, 138, 163, 122, 51, 39]; + blue = [ 121, 101, 58, 44, 47, 55, 57, 44, 43]; + break; + + // Dark Terrain + case 78: + red = [ 0, 41, 62, 79, 90, 87, 99, 140, 228]; + green = [ 0, 57, 81, 93, 85, 70, 71, 125, 228]; + blue = [ 95, 91, 91, 82, 60, 43, 44, 112, 228]; + break; + + // Fall + case 79: + red = [ 49, 59, 72, 88, 114, 141, 176, 205, 222]; + green = [ 78, 72, 66, 57, 59, 75, 106, 142, 173]; + blue = [ 78, 55, 46, 40, 39, 39, 40, 41, 47]; + break; + + // Fruit Punch + case 80: + red = [ 243, 222, 201, 185, 165, 158, 166, 187, 219]; + green = [ 94, 108, 132, 135, 125, 96, 68, 51, 61]; + blue = [ 7, 9, 12, 19, 45, 89, 118, 146, 118]; + break; + + // Fuchsia + case 81: + red = [ 19, 44, 74, 105, 137, 166, 194, 206, 220]; + green = [ 19, 28, 40, 55, 82, 110, 159, 181, 220]; + blue = [ 19, 42, 68, 96, 129, 157, 188, 203, 220]; + break; + + // Grey Yellow + case 82: + red = [ 33, 44, 70, 99, 140, 165, 199, 211, 216]; + green = [ 38, 50, 76, 105, 140, 165, 191, 189, 167]; + blue = [ 55, 67, 97, 124, 140, 166, 163, 129, 52]; + break; + + // Green Brown Terrain + case 83: + red = [ 0, 33, 73, 124, 136, 152, 159, 171, 223]; + green = [ 0, 43, 92, 124, 134, 126, 121, 144, 223]; + blue = [ 0, 43, 68, 76, 73, 64, 72, 114, 223]; + break; + + // Green Pink + case 84: + red = [ 5, 18, 45, 124, 193, 223, 205, 128, 49]; + green = [ 48, 134, 207, 230, 193, 113, 28, 0, 7]; + blue = [ 6, 15, 41, 121, 193, 226, 208, 130, 49]; + break; + + // Island + case 85: + red = [ 180, 106, 104, 135, 164, 188, 189, 165, 144]; + green = [ 72, 126, 154, 184, 198, 207, 205, 190, 179]; + blue = [ 41, 120, 158, 188, 194, 181, 145, 100, 62]; + break; + + // Lake + case 86: + red = [ 57, 72, 94, 117, 136, 154, 174, 192, 215]; + green = [ 0, 33, 68, 109, 140, 171, 192, 196, 209]; + blue = [ 116, 137, 173, 201, 200, 201, 203, 190, 187]; + break; + + // Light Temperature + case 87: + red = [ 31, 71, 123, 160, 210, 222, 214, 199, 183]; + green = [ 40, 117, 171, 211, 231, 220, 190, 132, 65]; + blue = [ 234, 214, 228, 222, 210, 160, 105, 60, 34]; + break; + + // Light Terrain + case 88: + red = [ 123, 108, 109, 126, 154, 172, 188, 196, 218]; + green = [ 184, 138, 130, 133, 154, 175, 188, 196, 218]; + blue = [ 208, 130, 109, 99, 110, 122, 150, 171, 218]; + break; + + // Mint + case 89: + red = [ 105, 106, 122, 143, 159, 172, 176, 181, 207]; + green = [ 252, 197, 194, 187, 174, 162, 153, 136, 125]; + blue = [ 146, 133, 144, 155, 163, 167, 166, 162, 174]; + break; + + // Neon + case 90: + red = [ 171, 141, 145, 152, 154, 159, 163, 158, 177]; + green = [ 236, 143, 100, 63, 53, 55, 44, 31, 6]; + blue = [ 59, 48, 46, 44, 42, 54, 82, 112, 179]; + break; + + // Pastel + case 91: + red = [ 180, 190, 209, 223, 204, 228, 205, 152, 91]; + green = [ 93, 125, 147, 172, 181, 224, 233, 198, 158]; + blue = [ 236, 218, 160, 133, 114, 132, 162, 220, 218]; + break; + + // Pearl + case 92: + red = [ 225, 183, 162, 135, 115, 111, 119, 145, 211]; + green = [ 205, 177, 166, 135, 124, 117, 117, 132, 172]; + blue = [ 186, 165, 155, 135, 126, 130, 150, 178, 226]; + break; + + // Pigeon + case 93: + red = [ 39, 43, 59, 63, 80, 116, 153, 177, 223]; + green = [ 39, 43, 59, 74, 91, 114, 139, 165, 223]; + blue = [ 39, 50, 59, 70, 85, 115, 151, 176, 223]; + break; + + // Plum + case 94: + red = [ 0, 38, 60, 76, 84, 89, 101, 128, 204]; + green = [ 0, 10, 15, 23, 35, 57, 83, 123, 199]; + blue = [ 0, 11, 22, 40, 63, 86, 97, 94, 85]; + break; + + // Red Blue + case 95: + red = [ 94, 112, 141, 165, 167, 140, 91, 49, 27]; + green = [ 27, 46, 88, 135, 166, 161, 135, 97, 58]; + blue = [ 42, 52, 81, 106, 139, 158, 155, 137, 116]; + break; + + // Rose + case 96: + red = [ 30, 49, 79, 117, 135, 151, 146, 138, 147]; + green = [ 63, 60, 72, 90, 94, 94, 68, 46, 16]; + blue = [ 18, 28, 41, 56, 62, 63, 50, 36, 21]; + break; + + // Rust + case 97: + red = [ 0, 30, 63, 101, 143, 152, 169, 187, 230]; + green = [ 0, 14, 28, 42, 58, 61, 67, 74, 91]; + blue = [ 39, 26, 21, 18, 15, 14, 14, 13, 13]; + break; + + // Sandy Terrain + case 98: + red = [ 149, 140, 164, 179, 182, 181, 131, 87, 61]; + green = [ 62, 70, 107, 136, 144, 138, 117, 87, 74]; + blue = [ 40, 38, 45, 49, 49, 49, 38, 32, 34]; + break; + + // Sienna + case 99: + red = [ 99, 112, 148, 165, 179, 182, 183, 183, 208]; + green = [ 39, 40, 57, 79, 104, 127, 148, 161, 198]; + blue = [ 15, 16, 18, 33, 51, 79, 103, 129, 177]; + break; + + // Solar + case 100: + red = [ 99, 116, 154, 174, 200, 196, 201, 201, 230]; + green = [ 0, 0, 8, 32, 58, 83, 119, 136, 173]; + blue = [ 5, 6, 7, 9, 9, 14, 17, 19, 24]; + break; + + // South West + case 101: + red = [ 82, 106, 126, 141, 155, 163, 142, 107, 66]; + green = [ 62, 44, 69, 107, 135, 152, 149, 132, 119]; + blue = [ 39, 25, 31, 60, 73, 68, 49, 72, 188]; + break; + + // Starry Night + case 102: + red = [ 18, 29, 44, 72, 116, 158, 184, 208, 221]; + green = [ 27, 46, 71, 105, 146, 177, 189, 190, 183]; + blue = [ 39, 55, 80, 108, 130, 133, 124, 100, 76]; + break; + + // Sunset + case 103: + red = [ 0, 48, 119, 173, 212, 224, 228, 228, 245]; + green = [ 0, 13, 30, 47, 79, 127, 167, 205, 245]; + blue = [ 0, 68, 75, 43, 16, 22, 55, 128, 245]; + break; + + // Temperature Map + case 104: + red = [ 34, 70, 129, 187, 225, 226, 216, 193, 179]; + green = [ 48, 91, 147, 194, 226, 229, 196, 110, 12]; + blue = [ 234, 212, 216, 224, 206, 110, 53, 40, 29]; + break; + + // Thermometer + case 105: + red = [ 30, 55, 103, 147, 174, 203, 188, 151, 105]; + green = [ 0, 65, 138, 182, 187, 175, 121, 53, 9]; + blue = [ 191, 202, 212, 208, 171, 140, 97, 57, 30]; + break; + + // Valentine + case 106: + red = [ 112, 97, 113, 125, 138, 159, 178, 188, 225]; + green = [ 16, 17, 24, 37, 56, 81, 110, 136, 189]; + blue = [ 38, 35, 46, 59, 78, 103, 130, 152, 201]; + break; + + // Visible Spectrum + case 107: + red = [ 18, 72, 5, 23, 29, 201, 200, 98, 29]; + green = [ 0, 0, 43, 167, 211, 117, 0, 0, 0]; + blue = [ 51, 203, 177, 26, 10, 9, 8, 3, 0]; + break; + + // Water Melon + case 108: + red = [ 19, 42, 64, 88, 118, 147, 175, 187, 205]; + green = [ 19, 55, 89, 125, 154, 169, 161, 129, 70]; + blue = [ 19, 32, 47, 70, 100, 128, 145, 130, 75]; + break; + + // Cool + case 109: + red = [ 33, 31, 42, 68, 86, 111, 141, 172, 227]; + green = [ 255, 175, 145, 106, 88, 55, 15, 0, 0]; + blue = [ 255, 205, 202, 203, 208, 205, 203, 206, 231]; + break; + + // Copper + case 110: + red = [ 0, 25, 50, 79, 110, 145, 181, 201, 254]; + green = [ 0, 16, 30, 46, 63, 82, 101, 124, 179]; + blue = [ 0, 12, 21, 29, 39, 49, 61, 74, 103]; + break; + + // Gist Earth + case 111: + red = [ 0, 13, 30, 44, 72, 120, 156, 200, 247]; + green = [ 0, 36, 84, 117, 141, 153, 151, 158, 247]; + blue = [ 0, 94, 100, 82, 56, 66, 76, 131, 247]; + break; + + // Viridis + case 112: + red = [ 26, 51, 43, 33, 28, 35, 74, 144, 246]; + green = [ 9, 24, 55, 87, 118, 150, 180, 200, 222]; + blue = [ 30, 96, 112, 114, 112, 101, 72, 35, 0]; + break; + + default: + return JSROOT.Painter.CreateDefaultPalette(); + } + + return JSROOT.Painter.CreateGradientColorTable(stops, red, green, blue, 255, alfa); + } + + // ============================================================================== + + + JSROOT.Painter.drawEllipse = function(divid, obj, opt) { + + this.SetDivId(divid); + + this.Redraw = function() { + var ellipse = this.GetObject(); + + if(!this.lineatt) this.lineatt = JSROOT.Painter.createAttLine(ellipse); + if (!this.fillatt) this.fillatt = this.createAttFill(ellipse); + + // create svg:g container for ellipse drawing + this.RecreateDrawG(this.main_painter() == null); + + var x = this.AxisToSvg("x", ellipse.fX1); + var y = this.AxisToSvg("y", ellipse.fY1); + var rx = this.AxisToSvg("x", ellipse.fX1 + ellipse.fR1) - x; + var ry = y - this.AxisToSvg("y", ellipse.fY1 + ellipse.fR2); + + if ((ellipse.fPhimin == 0) && (ellipse.fPhimax == 360) && (ellipse.fTheta == 0)) { + // this is simple case, which could be drawn with svg:ellipse + this.draw_g + .append("svg:ellipse") + .attr("cx", x.toFixed(1)).attr("cy", y.toFixed(1)) + .attr("rx", rx.toFixed(1)).attr("ry", ry.toFixed(1)) + .call(this.lineatt.func).call(this.fillatt.func); + return; + } + + // here svg:path is used to draw more complex figure + + var ct = Math.cos(Math.PI*ellipse.fTheta/180.); + var st = Math.sin(Math.PI*ellipse.fTheta/180.); + + var dx1 = rx * Math.cos(ellipse.fPhimin*Math.PI/180.); + var dy1 = ry * Math.sin(ellipse.fPhimin*Math.PI/180.); + var x1 = dx1*ct - dy1*st; + var y1 = -dx1*st - dy1*ct; + + var dx2 = rx * Math.cos(ellipse.fPhimax*Math.PI/180.); + var dy2 = ry * Math.sin(ellipse.fPhimax*Math.PI/180.); + var x2 = dx2*ct - dy2*st; + var y2 = -dx2*st - dy2*ct; + + this.draw_g + .attr("transform","translate("+x.toFixed(1)+","+y.toFixed(1)+")") + .append("svg:path") + .attr("d", "M 0,0" + + " L " + x1.toFixed(1) + "," + y1.toFixed(1) + + " A " + rx.toFixed(1) + " " + ry.toFixed(1) + " " + -ellipse.fTheta.toFixed(1) + " 1 0 " + x2.toFixed(1) + "," + y2.toFixed(1) + + " L 0,0 Z") + .call(this.lineatt.func).call(this.fillatt.func); + } + + this.Redraw(); // actual drawing + return this.DrawingReady(); + } + + // ============================================================================= + + JSROOT.Painter.drawLine = function(divid, obj, opt) { + + this.SetDivId(divid); + + this.Redraw = function() { + var line = this.GetObject(), + lineatt = JSROOT.Painter.createAttLine(line); + + // create svg:g container for line drawing + this.RecreateDrawG(this.main_painter() == null); + + this.draw_g + .append("svg:line") + .attr("x1", this.AxisToSvg("x", line.fX1).toFixed(1)) + .attr("y1", this.AxisToSvg("y", line.fY1).toFixed(1)) + .attr("x2", this.AxisToSvg("x", line.fX2).toFixed(1)) + .attr("y2", this.AxisToSvg("y", line.fY2).toFixed(1)) + .call(lineatt.func); + } + + this.Redraw(); // actual drawing + + return this.DrawingReady(); + } + + // ============================================================================= + + JSROOT.Painter.drawBox = function(divid, obj, opt) { + + this.SetDivId(divid); + + this.Redraw = function() { + var box = this.GetObject(), + lineatt = JSROOT.Painter.createAttLine(box), + fillatt = this.createAttFill(box); + + // create svg:g container for line drawing + this.RecreateDrawG(this.main_painter() == null); + + var x1 = Math.round(this.AxisToSvg("x", box.fX1)), + x2 = Math.round(this.AxisToSvg("x", box.fX2)), + y1 = Math.round(this.AxisToSvg("y", box.fY1)), + y2 = Math.round(this.AxisToSvg("y", box.fY2)); + + this.draw_g + .append("svg:rect") + .attr("x", Math.min(x1,x2)) + .attr("y", Math.min(y1,y2)) + .attr("width", Math.abs(x2-x1)) + .attr("height", Math.abs(y1-y2)) + .call(lineatt.func) + .call(fillatt.func); + } + + this.Redraw(); // actual drawing + + return this.DrawingReady(); + } + + // ====================================================================================== + + JSROOT.Painter.drawArrow = function(divid, obj, opt) { + + this.SetDivId(divid); + + this.Redraw = function() { + var arrow = this.GetObject(); + if (!this.lineatt) this.lineatt = JSROOT.Painter.createAttLine(arrow); + if (!this.fillatt) this.fillatt = this.createAttFill(arrow); + + var wsize = Math.max(this.pad_width(), this.pad_height()) * arrow.fArrowSize; + if (wsize<3) wsize = 3; + var hsize = wsize * Math.tan(arrow.fAngle/2 * (Math.PI/180)); + + // create svg:g container for line drawing + this.RecreateDrawG(this.main_painter() == null); + + var x1 = this.AxisToSvg("x", arrow.fX1), + y1 = this.AxisToSvg("y", arrow.fY1), + x2 = this.AxisToSvg("x", arrow.fX2), + y2 = this.AxisToSvg("y", arrow.fY2), + right_arrow = "M0,0" + " L"+wsize.toFixed(1) +","+hsize.toFixed(1) + " L0," + (hsize*2).toFixed(1), + left_arrow = "M" + wsize.toFixed(1) + ", 0" + " L 0," + hsize.toFixed(1) + " L " + wsize.toFixed(1) + "," + (hsize*2).toFixed(1), + m_start = null, m_mid = null, m_end = null, defs = null, + oo = arrow.fOption, len = oo.length; + + if (oo.indexOf("<")==0) { + var closed = (oo.indexOf("<|") == 0); + if (!defs) defs = this.draw_g.append("defs"); + m_start = "jsroot_arrowmarker_" + JSROOT.Painter.arrowcnt++; + var beg = defs.append("svg:marker") + .attr("id", m_start) + .attr("markerWidth", wsize.toFixed(1)) + .attr("markerHeight", (hsize*2).toFixed(1)) + .attr("refX", "0") + .attr("refY", hsize.toFixed(1)) + .attr("orient", "auto") + .attr("markerUnits", "userSpaceOnUse") + .append("svg:path") + .style("fill","none") + .attr("d", left_arrow + (closed ? " Z" : "")) + .call(this.lineatt.func); + if (closed) beg.call(this.fillatt.func); + } + + var midkind = 0; + if (oo.indexOf("->-")>=0) midkind = 1; else + if (oo.indexOf("-|>-")>=0) midkind = 11; else + if (oo.indexOf("-<-")>=0) midkind = 2; else + if (oo.indexOf("-<|-")>=0) midkind = 12; + + if (midkind > 0) { + var closed = midkind > 10; + if (!defs) defs = this.draw_g.append("defs"); + m_mid = "jsroot_arrowmarker_" + JSROOT.Painter.arrowcnt++; + + var mid = defs.append("svg:marker") + .attr("id", m_mid) + .attr("markerWidth", wsize.toFixed(1)) + .attr("markerHeight", (hsize*2).toFixed(1)) + .attr("refX", (wsize*0.5).toFixed(1)) + .attr("refY", hsize.toFixed(1)) + .attr("orient", "auto") + .attr("markerUnits", "userSpaceOnUse") + .append("svg:path") + .style("fill","none") + .attr("d", ((midkind % 10 == 1) ? right_arrow : left_arrow) + + ((midkind > 10) ? " Z" : "")) + .call(this.lineatt.func); + if (midkind > 10) mid.call(this.fillatt.func); + } + + if (oo.lastIndexOf(">") == len-1) { + var closed = (oo.lastIndexOf("|>") == len-2) && (len>1); + if (!defs) defs = this.draw_g.append("defs"); + m_end = "jsroot_arrowmarker_" + JSROOT.Painter.arrowcnt++; + var end = defs.append("svg:marker") + .attr("id", m_end) + .attr("markerWidth", wsize.toFixed(1)) + .attr("markerHeight", (hsize*2).toFixed(1)) + .attr("refX", wsize.toFixed(1)) + .attr("refY", hsize.toFixed(1)) + .attr("orient", "auto") + .attr("markerUnits", "userSpaceOnUse") + .append("svg:path") + .style("fill","none") + .attr("d", right_arrow + (closed ? " Z" : "")) + .call(this.lineatt.func); + if (closed) end.call(this.fillatt.func); + } + + var path = this.draw_g + .append("svg:path") + .attr("d", "M" + x1.toFixed(1) + "," + y1.toFixed(1) + + ((m_mid == null) ? "" : "L" + (x1/2+x2/2).toFixed(1) + "," + (y1/2+y2/2).toFixed(1)) + + " L" + x2.toFixed(1) + "," + y2.toFixed(1)) + .call(this.lineatt.func); + + if (m_start!=null) path.style("marker-start","url(#" + m_start + ")"); + if (m_mid!=null) path.style("marker-mid","url(#" + m_mid + ")"); + if (m_end!=null) path.style("marker-end","url(#" + m_end + ")"); + } + + if (!('arrowcnt' in JSROOT.Painter)) JSROOT.Painter.arrowcnt = 0; + + this.Redraw(); // actual drawing + return this.DrawingReady(); + } + + // ================================================================================ + + JSROOT.Painter.BuildSvgPath = function(kind, bins, height, ndig) { + // function used to provide svg:path for the smoothed curves + // reuse code from d3.js. Used in TF1 and TGraph painters + // kind should contain "bezier" or "line". If first symbol "L", than it used to continue drawing + + var smooth = kind.indexOf("bezier") >= 0; + + if (ndig===undefined) ndig = smooth ? 2 : 0; + if (height===undefined) height = 0; + + function jsroot_d3_svg_lineSlope(p0, p1) { + return (p1.gry - p0.gry) / (p1.grx - p0.grx); + } + function jsroot_d3_svg_lineFiniteDifferences(points) { + var i = 0, j = points.length - 1, m = [], p0 = points[0], p1 = points[1], d = m[0] = jsroot_d3_svg_lineSlope(p0, p1); + while (++i < j) { + m[i] = (d + (d = jsroot_d3_svg_lineSlope(p0 = p1, p1 = points[i + 1]))) / 2; + } + m[i] = d; + return m; + } + function jsroot_d3_svg_lineMonotoneTangents(points) { + var d, a, b, s, m = jsroot_d3_svg_lineFiniteDifferences(points), i = -1, j = points.length - 1; + while (++i < j) { + d = jsroot_d3_svg_lineSlope(points[i], points[i + 1]); + if (Math.abs(d) < 1e-6) { + m[i] = m[i + 1] = 0; + } else { + a = m[i] / d; + b = m[i + 1] / d; + s = a * a + b * b; + if (s > 9) { + s = d * 3 / Math.sqrt(s); + m[i] = s * a; + m[i + 1] = s * b; + } + } + } + i = -1; + while (++i <= j) { + s = (points[Math.min(j, i + 1)].grx - points[Math.max(0, i - 1)].grx) / (6 * (1 + m[i] * m[i])); + points[i].dgrx = s || 0; + points[i].dgry = m[i]*s || 0; + } + } + + var res = {}, bin = bins[0], prev, maxy = Math.max(bin.gry, height+5), + currx = Math.round(bin.grx), curry = Math.round(bin.gry), dx, dy; + + res.path = ((kind.charAt(0) == "L") ? "L" : "M") + + bin.grx.toFixed(ndig) + "," + bin.gry.toFixed(ndig); + + // just calculate all deltas, can be used to build exclusion + if (smooth || kind.indexOf('calc')>=0) + jsroot_d3_svg_lineMonotoneTangents(bins); + + if (smooth) { + res.path += "c" + bin.dgrx.toFixed(ndig) + "," + bin.dgry.toFixed(ndig) + ","; + } + + for(n=1; n 1) res.path += "s"; + res.path += (bin.grx-bin.dgrx-prev.grx).toFixed(ndig) + "," + (bin.gry-bin.dgry-prev.gry).toFixed(ndig) + "," + (bin.grx-prev.grx).toFixed(ndig) + "," + (bin.gry-prev.gry).toFixed(ndig); + maxy = Math.max(maxy, prev.gry); + } else { + dx = Math.round(bin.grx - currx); + dy = Math.round(bin.gry - curry); + res.path += "l" + dx + "," + dy; + currx+=dx; curry+=dy; + maxy = Math.max(maxy, curry); + } + } + + if (height>0) + res.close = "L" + bin.grx.toFixed(ndig) +"," + maxy.toFixed(ndig) + + "L" + bins[0].grx.toFixed(ndig) +"," + maxy.toFixed(ndig) + "Z"; + + return res; + } + + + // =================================================================================== + + JSROOT.Painter.drawFunction = function(divid, tf1, opt) { + this.bins = null; + + this.Eval = function(x) { + return this.GetObject().evalPar(x); + } + + this.CreateBins = function(ignore_zoom) { + var main = this.main_painter(), gxmin = 0, gxmax = 0, tf1 = this.GetObject(); + + if ((main!==null) && !ignore_zoom) { + if (main.zoom_xmin !== main.zoom_xmax) { + gxmin = main.zoom_xmin; + gxmax = main.zoom_xmax; + } else { + gxmin = main.xmin; + gxmax = main.xmax; + } + } + + if (tf1.fSave.length > 0) { + // in the case where the points have been saved, useful for example + // if we don't have the user's function + var np = tf1.fSave.length - 2, + xmin = tf1.fSave[np], + xmax = tf1.fSave[np+1], + dx = (xmax - xmin) / (np-1), + res = []; + + for (var n=0; n < np; ++n) { + var xx = xmin + dx*n; + // check if points need to be displayed at all, keep at least 4-5 points for Bezier curves + if ((gxmin !== gxmax) && ((xx + 2*dx < gxmin) || (xx - 2*dx > gxmax))) continue; + + res.push({ x: xx, y: tf1.fSave[n] }); + } + return res; + } + + var xmin = tf1.fXmin, xmax = tf1.fXmax, logx = false, pad = this.root_pad(); + + if (gxmin !== gxmax) { + if (gxmin > xmin) xmin = gxmin; + if (gxmax < xmax) xmax = gxmax; + } + + if ((main!==null) && main.logx && (xmin>0) && (xmax>0)) { + logx = true; + xmin = Math.log(xmin); + xmax = Math.log(xmax); + } + + var np = Math.max(tf1.fNpx, 101); + var dx = (xmax - xmin) / (np - 1); + + var res = []; + for (var n=0; n < np; n++) { + var xx = xmin + n*dx; + if (logx) xx = Math.exp(xx); + var yy = this.Eval(xx); + if (!isNaN(yy)) res.push({ x : xx, y : yy }); + } + return res; + } + + this.CreateDummyHisto = function() { + + var xmin = 0, xmax = 1, ymin = 0, ymax = 1; + + var bins = this.CreateBins(true); + + if (bins!==null) { + + xmin = xmax = bins[0].x; + ymin = ymax = bins[0].y; + + bins.forEach(function(bin) { + xmin = Math.min(bin.x, xmin); + xmax = Math.max(bin.x, xmax); + ymin = Math.min(bin.y, ymin); + ymax = Math.max(bin.y, ymax); + }); + + if (ymax > 0.0) ymax *= 1.05; + if (ymin < 0.0) ymin *= 1.05; + } + + var histo = JSROOT.Create("TH1I"), + tf1 = this.GetObject(); + + histo.fName = tf1.fName + "_hist"; + histo.fTitle = tf1.fTitle; + + histo.fXaxis.fXmin = xmin; + histo.fXaxis.fXmax = xmax; + histo.fYaxis.fXmin = ymin; + histo.fYaxis.fXmax = ymax; + + return histo; + } + + this.ProcessTooltipFunc = function(pnt) { + var cleanup = false; + + if ((pnt === null) || (this.bins===null)) { + cleanup = true; + } else + if ((this.bins.length==0) || (pnt.x < this.bins[0].grx) || (pnt.x > this.bins[this.bins.length-1].grx)) { + cleanup = true; + } + + if (cleanup) { + if (this.draw_g !== null) + this.draw_g.select(".tooltip_bin").remove(); + return null; + } + + var min = 100000, best = -1, bin; + + for(var n=0; n 0) res.lines.push(name); + + var pmain = this.main_painter(); + if (pmain!==null) + res.lines.push("x = " + pmain.AxisAsText("x",bin.x) + " y = " + pmain.AxisAsText("y",bin.y)); + + return res; + } + + this.Redraw = function() { + + var w = this.frame_width(), h = this.frame_height(), tf1 = this.GetObject(); + + this.RecreateDrawG(false, "main_layer"); + + // recalculate drawing bins when necessary + this.bins = this.CreateBins(false); + + var pthis = this; + var pmain = this.main_painter(); + var name = this.GetTipName("\n"); + + if (!this.lineatt) + this.lineatt = JSROOT.Painter.createAttLine(tf1); + this.lineatt.used = false; + if (!this.fillatt) + this.fillatt = this.createAttFill(tf1, undefined, undefined, 1); + this.fillatt.used = false; + + var n, bin; + // first calculate graphical coordinates + for(n=0; n 2) { + + var h0 = h; // use maximal frame height for filling + if ((pmain.hmin!==undefined) && (pmain.hmin>=0)) { + h0 = Math.round(pmain.gry(0)); + if ((h0 > h) || (h0 < 0)) h0 = h; + } + + var path = JSROOT.Painter.BuildSvgPath("bezier", this.bins, h0, 2); + + if (this.lineatt.color != "none") + this.draw_g.append("svg:path") + .attr("class", "line") + .attr("d", path.path) + .style("fill", "none") + .call(this.lineatt.func); + + if (this.fillatt.color != "none") + this.draw_g.append("svg:path") + .attr("class", "area") + .attr("d", path.path + path.close) + .style("stroke", "none") + .call(this.fillatt.func); + } + + delete this.ProcessTooltip; + + if (JSROOT.gStyle.Tooltip > 0) + this.ProcessTooltip = this.ProcessTooltipFunc; + } + + this.CanZoomIn = function(axis,min,max) { + if (axis!=="x") return false; + + var tf1 = this.GetObject(); + + if (tf1.fSave.length > 0) { + // in the case where the points have been saved, useful for example + // if we don't have the user's function + var nb_points = tf1.fNpx; + + var xmin = tf1.fSave[nb_points + 1]; + var xmax = tf1.fSave[nb_points + 2]; + + return Math.abs(xmin - xmax) / nb_points < Math.abs(min - max); + } + + // if function calculated, one always could zoom inside + return true; + } + + this.SetDivId(divid, -1); + if (this.main_painter() === null) { + var histo = this.CreateDummyHisto(); + JSROOT.Painter.drawHistogram1D(divid, histo, "AXIS"); + } + this.SetDivId(divid); + this.Redraw(); + return this.DrawingReady(); + } + + // ==================================================================== + + JSROOT.Painter.drawHStack = function(divid, stack, opt) { + // paint the list of histograms + // By default, histograms are shown stacked. + // -the first histogram is paint + // -then the sum of the first and second, etc + + // 'this' pointer set to created painter instance + this.nostack = false; + this.firstpainter = null; + this.painters = new Array; // keep painters to be able update objects + + this.SetDivId(divid); + + if (!('fHists' in stack) || (stack.fHists.arr.length == 0)) return this.DrawingReady(); + + this['BuildStack'] = function() { + // build sum of all histograms + // Build a separate list fStack containing the running sum of all histograms + + var stack = this.GetObject(); + + if (!('fHists' in stack)) return false; + var nhists = stack.fHists.arr.length; + if (nhists <= 0) return false; + var lst = JSROOT.Create("TList"); + lst.Add(JSROOT.clone(stack.fHists.arr[0])); + for (var i=1;i res.max))) res.max = val+err; + } + } + + return res; + } + + this['GetMinMax'] = function(opt) { + var res = { min : 0, max : 0 }, + iserr = (opt.indexOf('e')>=0), + stack = this.GetObject(); + + if (this.nostack) { + for (var i = 0; i < stack.fHists.arr.length; ++i) { + var resh = this.GetHistMinMax(stack.fHists.arr[i], iserr); + if (i==0) res = resh; else { + if (resh.min < res.min) res.min = resh.min; + if (resh.max > res.max) res.max = resh.max; + } + } + + if (stack.fMaximum != -1111) + res.max = stack.fMaximum; + else + res.max *= 1.05; + + if (stack.fMinimum != -1111) res.min = stack.fMinimum; + } else { + res.min = this.GetHistMinMax(stack.fStack.arr[0], iserr).min; + res.max = this.GetHistMinMax(stack.fStack.arr[stack.fStack.arr.length-1], iserr).max * 1.05; + } + + var pad = this.root_pad(); + if (pad && pad.fLogy) { + if (res.min<0) res.min = res.max * 1e-4; + } + + return res; + } + + this['DrawNextHisto'] = function(indx, opt) { + var hist = null, + stack = this.GetObject(), + nhists = stack.fHists.arr.length; + + if (indx>=nhists) return this.DrawingReady(); + + if (indx<0) hist = stack.fHistogram; else + if (this.nostack) hist = stack.fHists.arr[indx]; + else hist = stack.fStack.arr[nhists - indx - 1]; + + var hopt = hist.fOption; + if ((opt != "") && (hopt.indexOf(opt) == -1)) hopt += opt; + if (indx>=0) hopt += "same"; + var subp = JSROOT.draw(this.divid, hist, hopt); + if (indx<0) this.firstpainter = subp; + else this.painters.push(subp); + subp.WhenReady(this.DrawNextHisto.bind(this, indx+1, opt)); + } + + this['drawStack'] = function(opt) { + var pad = this.root_pad(), + stack = this.GetObject(), + histos = stack.fHists, + nhists = histos.arr.length; + + if (opt == null) opt = ""; + else opt = opt.toLowerCase(); + + var lsame = false; + if (opt.indexOf("same") != -1) { + lsame = true; + opt.replace("same", ""); + } + this.nostack = opt.indexOf("nostack") < 0 ? false : true; + + // when building stack, one could fail to sum up histograms + if (!this.nostack) + this.nostack = ! this.BuildStack(); + + var mm = this.GetMinMax(opt); + + if (stack.fHistogram === null) { + // compute the min/max of each axis + var xmin = 0, xmax = 0, ymin = 0, ymax = 0; + for (var i = 0; i < nhists; ++i) { + var h = histos.arr[i]; + if (i == 0 || h.fXaxis.fXmin < xmin) + xmin = h.fXaxis.fXmin; + if (i == 0 || h.fXaxis.fXmax > xmax) + xmax = h.fXaxis.fXmax; + if (i == 0 || h.fYaxis.fXmin < ymin) + ymin = h.fYaxis.fXmin; + if (i == 0 || h.fYaxis.fXmax > ymax) + ymax = h.fYaxis.fXmax; + } + + var h = stack.fHists.arr[0]; + stack.fHistogram = JSROOT.Create("TH1I"); + stack.fHistogram.fName = "unnamed"; + stack.fHistogram.fXaxis = JSROOT.clone(h.fXaxis); + stack.fHistogram.fYaxis = JSROOT.clone(h.fYaxis); + stack.fHistogram.fXaxis.fXmin = xmin; + stack.fHistogram.fXaxis.fXmax = xmax; + stack.fHistogram.fYaxis.fXmin = ymin; + stack.fHistogram.fYaxis.fXmax = ymax; + } + stack.fHistogram.fTitle = stack.fTitle; + var histo = stack.fHistogram; + if (!histo.TestBit(JSROOT.TH1StatusBits.kIsZoomed)) { + if (pad && pad.fLogy) + histo.fMaximum = mm.max * (1 + 0.2 * JSROOT.log10(mm.max / mm.min)); + else + histo.fMaximum = mm.max; + if (pad && pad.fLogy) + histo.fMinimum = mm.min / (1 + 0.5 * JSROOT.log10(mm.max / mm.min)); + else + histo.fMinimum = mm.min; + } + + this.DrawNextHisto(!lsame ? -1 : 0, opt); + return this; + } + + this['UpdateObject'] = function(obj) { + if (!this.MatchObjectType(obj)) return false; + + var isany = false; + if (this.firstpainter) + if (this.firstpainter.UpdateObject(obj.fHistogram)) isany = true; + + var nhists = obj.fHists.arr.length; + for (var i = 0; i < nhists; ++i) { + var hist = this.nostack ? obj.fHists.arr[i] : obj.fStack.arr[nhists - i - 1]; + if (this.painters[i].UpdateObject(hist)) isany = true; + } + + return isany; + } + + return this.drawStack(opt); + } + + // ======================================================================= + + JSROOT.TGraphPainter = function(graph) { + JSROOT.TObjectPainter.call(this, graph); + this.ownhisto = false; // indicate if graph histogram was drawn for axes + this.bins = null; + this.xmin = this.ymin = this.xmax = this.ymax = 0; + } + + JSROOT.TGraphPainter.prototype = Object.create(JSROOT.TObjectPainter.prototype); + + JSROOT.TGraphPainter.prototype.Redraw = function() { + this.DrawBins(); + } + + JSROOT.TGraphPainter.prototype.DecodeOptions = function(opt) { + this.draw_all = true; + JSROOT.extend(this, { optionLine:0, optionAxis:0, optionCurve:0, optionRect:0, + optionMark:0, optionBar:0, optionR:0, optionE:0, optionEF:0, + optionFill:0, optionZ:0, optionBrackets:0, + opt:"LP", out_of_range: false, has_errors: false, draw_errors: false, is_bent:false }); + + var graph = this.GetObject(); + + this.is_bent = graph._typename == 'TGraphBentErrors'; + this.has_errors = (graph._typename == 'TGraphErrors' || + graph._typename == 'TGraphAsymmErrors' || + this.is_bent || graph._typename.match(/^RooHist/)); + this.draw_errors = this.has_errors; + + if ((opt != null) && (opt != "")) { + this.opt = opt.toUpperCase(); + this.opt.replace('SAME', ''); + } + if (this.opt.indexOf('L') != -1) + this.optionLine = 1; + if (this.opt.indexOf('F') != -1) + this.optionFill = 1; + if (this.opt.indexOf('A') != -1) + this.optionAxis = 1; + if (this.opt.indexOf('C') != -1) { + this.optionCurve = 1; + if (this.optionFill==0) this.optionLine = 1; + } + if (this.opt.indexOf('*') != -1) + this.optionMark = 2; + if (this.opt.indexOf('P') != -1) + this.optionMark = 1; + if (this.opt.indexOf('B') != -1) { + this.optionBar = 1; + this.draw_errors = false; + } + if (this.opt.indexOf('R') != -1) + this.optionR = 1; + + if (this.opt.indexOf('[]') != -1) { + this.optionBrackets = 1; + this.draw_errors = false; + } + + if (this.opt.indexOf('0') != -1) { + this.optionMark = 1; + this.draw_errors = true; + this.out_of_range = true; + } + + if (this.opt.indexOf('1') != -1) { + if (this.optionBar == 1) this.optionBar = 2; + } + if (this.opt.indexOf('2') != -1) + this.optionRect = 1; + + if (this.opt.indexOf('3') != -1) { + this.optionEF = 1; + this.optionLine = 0; + this.draw_errors = false; + } + if (this.opt.indexOf('4') != -1) { + this.optionEF = 2; + this.optionLine = 0; + this.draw_errors = false; + } + + if (this.opt.indexOf('2') != -1 || this.opt.indexOf('5') != -1) this.optionE = 1; + + // special case - one could use scg:path to draw many pixels ( + if ((this.optionMark==1) && (graph.fMarkerStyle==1)) this.optionMark = 3; + + // if no drawing option is selected and if opt<>' ' nothing is done. + if (this.optionLine + this.optionFill + this.optionMark + this.optionBar + this.optionE + + this.optionEF + this.optionRect + this.optionBrackets == 0) { + if (this.opt.length == 0) + this.optionLine = 1; + } + + if (graph._typename == 'TGraphErrors') { + var maxEX = d3.max(graph.fEX); + var maxEY = d3.max(graph.fEY); + if (maxEX < 1.0e-300 && maxEY < 1.0e-300) + this.draw_errors = false; + } + } + + JSROOT.TGraphPainter.prototype.CreateBins = function() { + var gr = this.GetObject(); + if (gr===null) return; + + var p, kind = 0, npoints = gr.fNpoints; + if ((gr._typename==="TCutG") && (npoints>3)) npoints--; + + if (gr._typename == 'TGraphErrors') kind = 1; else + if (gr._typename == 'TGraphAsymmErrors' || gr._typename == 'TGraphBentErrors' + || gr._typename.match(/^RooHist/)) kind = 2; + + this.bins = []; + + for (p=0;p 0) { + this.xmin = Math.min(this.xmin, bin.x - bin.exlow, bin.x + bin.exhigh); + this.xmax = Math.max(this.xmax, bin.x - bin.exlow, bin.x + bin.exhigh); + this.ymin = Math.min(this.ymin, bin.y - bin.eylow, bin.y + bin.eyhigh); + this.ymax = Math.max(this.ymax, bin.y - bin.eylow, bin.y + bin.eyhigh); + } else { + this.xmin = Math.min(this.xmin, bin.x); + this.xmax = Math.max(this.xmax, bin.x); + this.ymin = Math.min(this.ymin, bin.y); + this.ymax = Math.max(this.ymax, bin.y); + } + + } + } + + JSROOT.TGraphPainter.prototype.CreateHistogram = function() { + // bins should be created + + var xmin = this.xmin, xmax = this.xmax, ymin = this.ymin, ymax = this.ymax; + + if (xmin >= xmax) xmax = xmin+1; + if (ymin >= ymax) ymax = ymin+1; + var dx = (xmax-xmin)*0.1, dy = (ymax-ymin)*0.1, + uxmin = xmin - dx, uxmax = xmax + dx, + minimum = ymin - dy, maximum = ymax + dy; + + if ((uxmin<0) && (xmin>=0)) uxmin = xmin*0.9; + if ((uxmax>0) && (xmax<=0)) uxmax = 0; + + var graph = this.GetObject(); + + if (graph.fMinimum != -1111) minimum = ymin = graph.fMinimum; + if (graph.fMaximum != -1111) maximum = ymax = graph.fMaximum; + if ((minimum < 0) && (ymin >=0)) minimum = 0.9*ymin; + + var histo = JSROOT.CreateTH1(100); + histo.fName = graph.fName + "_h"; + histo.fTitle = graph.fTitle; + histo.fXaxis.fXmin = uxmin; + histo.fXaxis.fXmax = uxmax; + histo.fYaxis.fXmin = minimum; + histo.fYaxis.fXmax = maximum; + histo.fMinimum = minimum; + histo.fMaximum = maximum; + histo.fBits = histo.fBits | JSROOT.TH1StatusBits.kNoStats; + return histo; + } + + JSROOT.TGraphPainter.prototype.OptimizeBins = function(filter_func) { + if ((this.bins.length < 30) && !filter_func) return this.bins; + + var selbins = null; + if (typeof filter_func == 'function') { + for (var n = 0; n < this.bins.length; ++n) { + if (filter_func(this.bins[n],n)) { + if (selbins==null) + selbins = (n==0) ? [] : this.bins.slice(0, n); + } else { + if (selbins != null) selbins.push(this.bins[n]); + } + } + } + if (selbins == null) selbins = this.bins; + + if ((selbins.length < 5000) || (JSROOT.gStyle.OptimizeDraw == 0)) return selbins; + var step = Math.floor(selbins.length / 5000); + if (step < 2) step = 2; + var optbins = []; + for (var n = 0; n < selbins.length; n+=step) + optbins.push(selbins[n]); + + return optbins; + } + + JSROOT.TGraphPainter.prototype.TooltipText = function(d, asarray) { + var pmain = this.main_painter(), lines = []; + + lines.push(this.GetTipName()); + lines.push("x = " + pmain.AxisAsText("x", d.x)); + lines.push("y = " + pmain.AxisAsText("y", d.y)); + + if (this.draw_errors && (pmain.x_kind=='normal') && ('exlow' in d) && ((d.exlow!=0) || (d.exhigh!=0))) + lines.push("error x = -" + pmain.AxisAsText("x", d.exlow) + + "/+" + pmain.AxisAsText("x", d.exhigh)); + + if ((this.draw_errors || (this.optionEF > 0)) && (pmain.y_kind=='normal') && ('eylow' in d) && ((d.eylow!=0) || (d.eyhigh!=0)) ) + lines.push("error y = -" + pmain.AxisAsText("y", d.eylow) + + "/+" + pmain.AxisAsText("y", d.eyhigh)); + + if (asarray) return lines; + + var res = ""; + for (var n=0;n0 ? "\n" : "") + lines[n]); + return res; + } + + JSROOT.TGraphPainter.prototype.DrawBins = function() { + + this.RecreateDrawG(false, "main_layer"); + + var pthis = this, + pmain = this.main_painter(), + w = this.frame_width(), + h = this.frame_height(), + graph = this.GetObject(), + excl_width = 0; + + if (!this.lineatt) + this.lineatt = JSROOT.Painter.createAttLine(graph, undefined, true); + if (!this.fillatt) + this.fillatt = this.createAttFill(graph, undefined, undefined, 1); + this.fillatt.used = false; + + if (this.fillatt) this.fillatt.used = false; // mark used only when really used + this.draw_kind = "none"; // indicate if special svg:g were created for each bin + this.marker_size = 0; // indicate if markers are drawn + + if (this.lineatt.excl_side!=0) { + excl_width = this.lineatt.excl_side * this.lineatt.excl_width; + if (this.lineatt.width>0) this.optionLine = 1; + } + + var drawbins = null; + + if (this.optionEF > 0) { + + drawbins = this.OptimizeBins(); + + // build lower part + for (var n=0;n 1 ? "bezier" : "line", drawbins), + bins2 = []; + + for (var n=drawbins.length-1;n>=0;--n) { + var bin = drawbins[n]; + bin.gry = pmain.gry(bin.y + bin.eyhigh); + bins2.push(bin); + } + + // build upper part (in reverse direction + var path2 = JSROOT.Painter.BuildSvgPath(this.optionEF > 1 ? "Lbezier" : "Lline", bins2); + + this.draw_g.append("svg:path") + .attr("d", path1.path + path2.path + "Z") + .style("stroke", "none") + .call(this.fillatt.func); + this.draw_kind = "lines"; + } + + if (this.optionLine == 1 || this.optionFill == 1 || (excl_width!==0)) { + + var close_symbol = ""; + if (graph._typename=="TCutG") this.optionFill = 1; + + if (this.optionFill == 1) { + close_symbol = "Z"; // always close area if we want to fill it + excl_width=0; + } + + if (drawbins===null) drawbins = this.OptimizeBins(); + + for (var n=0;n=0;--n) { + var bin = drawbins[n]; + var dlen = Math.sqrt(bin.dgrx*bin.dgrx + bin.dgry*bin.dgry); + // shift point, using + bin.grx += excl_width*bin.dgry/dlen; + bin.gry -= excl_width*bin.dgrx/dlen; + extrabins.push(bin); + } + + var path2 = JSROOT.Painter.BuildSvgPath("L" + ((this.optionCurve === 1) ? "bezier" : "line"), extrabins); + + this.draw_g.append("svg:path") + .attr("d", path.path + path2.path + "Z") + .style("stroke", "none") + .call(this.fillatt.func) + .style('opacity', 0.75); + } + + if (this.optionLine || this.optionFill) { + var elem = this.draw_g.append("svg:path") + .attr("d", path.path + close_symbol); + if (this.optionLine) + elem.call(this.lineatt.func); + else + elem.style('stroke','none'); + + if (this.optionFill > 0) + elem.call(this.fillatt.func); + else + elem.style('fill','none'); + } + + this.draw_kind = "lines"; + } + + var nodes = null; + + if (this.draw_errors || this.optionRect || this.optionBrackets || this.optionBar) { + + drawbins = this.OptimizeBins(function(pnt,i) { + + var grx = pmain.grx(pnt.x); + + // when drawing bars, take all points + if (!pthis.optionBar && ((grx<0) || (grx>w))) return true; + + var gry = pmain.gry(pnt.y); + + if (!pthis.optionBar && !pthis.out_of_range && ((gry<0) || (gry>h))) return true; + + pnt.grx1 = Math.round(grx); + pnt.gry1 = Math.round(gry); + + if (pthis.has_errors) { + pnt.grx0 = Math.round(pmain.grx(pnt.x - pnt.exlow) - grx); + pnt.grx2 = Math.round(pmain.grx(pnt.x + pnt.exhigh) - grx); + pnt.gry0 = Math.round(pmain.gry(pnt.y - pnt.eylow) - gry); + pnt.gry2 = Math.round(pmain.gry(pnt.y + pnt.eyhigh) - gry); + + if (pthis.is_bent) { + pnt.grdx0 = Math.round(pmain.gry(pnt.y + graph.fEXlowd[i]) - gry); + pnt.grdx2 = Math.round(pmain.gry(pnt.y + graph.fEXhighd[i]) - gry); + pnt.grdy0 = Math.round(pmain.grx(pnt.x + graph.fEYlowd[i]) - grx); + pnt.grdy2 = Math.round(pmain.grx(pnt.x + graph.fEYhighd[i]) - grx); + } else { + pnt.grdx0 = pnt.grdx2 = pnt.grdy0 = pnt.grdy2 = 0; + } + } + + return false; + }); + + this.draw_kind = "nodes"; + + // here are up to five elements are collected, try to group them + nodes = this.draw_g.selectAll(".grpoint") + .data(drawbins) + .enter() + .append("svg:g") + .attr("class", "grpoint") + .attr("transform", function(d) { return "translate(" + d.grx1 + "," + d.gry1 + ")"; }); + } + + if (this.optionBar) { + // calculate bar width + for (var i=1;i yy0) ? yy0-d.gry1 : 0; + }) + .attr("width", function(d) { return Math.round(d.width); }) + .attr("height", function(d) { + if (pthis.optionBar!==1) return h > d.gry1 ? h - d.gry1 : 0; + return Math.abs(yy0 - d.gry1); + }) + .call(this.fillatt.func); + } + + if (this.optionRect) + nodes.filter(function(d) { return (d.exlow > 0) && (d.exhigh > 0) && (d.eylow > 0) && (d.eyhigh > 0); }) + .append("svg:rect") + .attr("x", function(d) { d.rect = true; return d.grx0; }) + .attr("y", function(d) { return d.gry2; }) + .attr("width", function(d) { return d.grx2 - d.grx0; }) + .attr("height", function(d) { return d.gry0 - d.gry2; }) + .call(this.fillatt.func); + + if (this.optionBrackets) { + nodes.filter(function(d) { return (d.eylow > 0) || (d.eyhigh > 0); }) + .append("svg:path") + .call(this.lineatt.func) + .style('fill', "none") + .attr("d", function(d) { + d.bracket = true; + return ((d.eylow > 0) ? "M-5,"+(d.gry0-3)+"v3h10v-3" : "") + + ((d.eyhigh > 0) ? "M-5,"+(d.gry2+3)+"v-3h10v3" : ""); + }); + } + + if (this.draw_errors) { + // to show end of error markers, use line width attribute + var lw = this.lineatt.width + JSROOT.gStyle.EndErrorSize, + vv = "m0," + lw + "v-" + 2*lw, + hh = "m" + lw + ",0h-" + 2*lw; + lw = Math.floor((this.lineatt.width-1)/2); // one shoud take into account half of end-cup line width + nodes.filter(function(d) { return (d.exlow > 0) || (d.exhigh > 0) || (d.eylow > 0) || (d.eyhigh > 0); }) + .append("svg:path") + .call(this.lineatt.func) + .style('fill', "none") + .attr("d", function(d) { + d.error = true; + return ((d.exlow > 0) ? "M0,0L"+(d.grx0+lw)+","+d.grdx0+vv : "") + + ((d.exhigh > 0) ? "M0,0L"+(d.grx2-lw)+","+d.grdx2+vv : "") + + ((d.eylow > 0) ? "M0,0L"+d.grdy0+","+(d.gry0-lw)+hh : "") + + ((d.eyhigh > 0) ? "M0,0L"+d.grdy2+","+(d.gry2+lw)+hh : ""); + }); + } + + if (this.optionMark > 0) { + // for tooltips use markers only if nodes where not created + var step = Math.max(1, Math.round(this.bins.length / 50000)), + path = "", n, pnt, grx, gry, marker_kind; + + if (this.optionMark==2) marker_kind = 3; else + if (this.optionMark==3) marker_kind = 1; + + if (!this.markeratt) + this.markeratt = JSROOT.Painter.createAttMarker(graph,marker_kind); + else + this.markeratt.Change(undefined, marker_kind); + + this.marker_size = this.markeratt.size; + + this.markeratt.reset_pos(); + + for (n=0;n -this.marker_size) && (grx < w+this.marker_size)) { + gry = pmain.gry(pnt.y); + if ((gry >-this.marker_size) && (gry < h+this.marker_size)) { + path += this.markeratt.create(grx, gry); + } + } + } + + if (path.length>0) { + this.draw_g.append("svg:path") + .attr("d", path) + .call(this.markeratt.func); + if ((nodes===null) && (this.draw_kind=="none")) + this.draw_kind = (this.optionMark==3) ? "path" : "mark"; + } + } + } + + JSROOT.TGraphPainter.prototype.ProcessTooltip = function(pnt) { + if (pnt === null) { + if (this.draw_g !== null) + this.draw_g.select(".tooltip_bin").remove(); + return null; + } + + if ((this.draw_kind=="lines") || (this.draw_kind=="path") || (this.draw_kind=="mark")) + return this.ProcessTooltipForPath(pnt); + + if (this.draw_kind!="nodes") return null; + + var width = this.frame_width(), + height = this.frame_height(), + pmain = this.main_painter(), + painter = this, + findbin = null, best_dist2 = 1e10, best = null; + + this.draw_g.selectAll('.grpoint').each(function() { + var d = d3.select(this).datum(); + if (d===undefined) return; + var dist2 = Math.pow(pnt.x - d.grx1, 2); + if (pnt.nproc===1) dist2 += Math.pow(pnt.y - d.gry1, 2); + if (dist2 >= best_dist2) return; + + var rect = null; + + if (d.error || d.rect || d.marker || d.bracket) { + rect = { x1: Math.min(-3, d.grx0), x2: Math.max(3, d.grx2), y1: Math.min(-3, d.gry2), y2: Math.max(3, d.gry0) }; + if (d.bracket) { rect.x1 = -5; rect.x2 = 5; } + } else + if (d.bar) { + rect = { x1: -d.width/2, x2: d.width/2, y1: 0, y2: height - d.gry1 }; + + if (painter.optionBar===1) { + var yy0 = pmain.gry(0); + rect.y1 = (d.gry1 > yy0) ? yy0-d.gry1 : 0; + rect.y2 = (d.gry1 > yy0) ? 0 : yy0-d.gry1; + } + } else { + rect = { x1: -5, x2: 5, y1: -5, y2: 5 }; + } + var matchx = (pnt.x >= d.grx1 + rect.x1) && (pnt.x <= d.grx1 + rect.x2); + var matchy = (pnt.y >= d.gry1 + rect.y1) && (pnt.y <= d.gry1 + rect.y2); + + if (matchx && (matchy || (pnt.nproc > 1))) { + best_dist2 = dist2; + findbin = this; + best = rect; + best.exact = matchx && matchy; + } + }); + + var ttrect = this.draw_g.select(".tooltip_bin"); + + if (findbin == null) { + ttrect.remove(); + return null; + } + + var d = d3.select(findbin).datum(); + + var res = { x: d.grx1, y: d.gry1, + color1: this.lineatt.color, + lines: this.TooltipText(d, true) }; + if (this.fillatt && this.fillatt.used) res.color2 = this.fillatt.color; + + if (best.exact) res.exact = true; + res.menu = res.exact; // activate menu only when exactly locate bin + res.menu_dist = 3; // distance alwyas fixed + + if (ttrect.empty()) + ttrect = this.draw_g.append("svg:rect") + .attr("class","tooltip_bin h1bin") + .style("pointer-events","none"); + + res.changed = ttrect.property("current_bin") !== findbin; + + if (res.changed) + ttrect.attr("x", d.grx1 + best.x1) + .attr("width", best.x2 - best.x1) + .attr("y", d.gry1 + best.y1) + .attr("height", best.y2 - best.y1) + .style("opacity", "0.3") + .property("current_bin", findbin); + + return res; + } + + JSROOT.TGraphPainter.prototype.ProcessTooltipForPath = function(pnt) { + + if (this.bins === null) return null; + + var islines = (this.draw_kind=="lines"), + ismark = (this.draw_kind=="mark"), + bestbin = null, + bestdist = 1e10, + pmain = this.main_painter(), + dist, grx, gry, n, bin; + + for (n=0;n 10) && islines) bestbin = null; + + var radius = Math.max(this.lineatt.width + 3, 4); + + if (this.marker_size > 0) radius = Math.max(Math.round(this.marker_size*7), radius); + + if (bestbin !== null) + bestdist = Math.sqrt(Math.pow(pnt.x-pmain.grx(bestbin.x),2) + Math.pow(pnt.y-pmain.gry(bestbin.y),2)); + + // console.log('draw kind', this.draw_kind, 'best dist', bestdist,'best bin', bestbin); + + if (!islines && !ismark && (bestdist>radius)) bestbin = null; + + if (ismark && (bestbin!==null)) { + if ((pnt.nproc == 1) && (bestdist>radius)) bestbin = null; else + if ((this.bins.length==1) && (bestdist>3*radius)) bestbin = null; + } + + var ttbin = this.draw_g.select(".tooltip_bin"); + + if (bestbin===null) { + ttbin.remove(); + return null; + } + + var res = { x: pmain.grx(bestbin.x), y: pmain.gry(bestbin.y), + color1: this.lineatt.color, + lines: this.TooltipText(bestbin, true) }; + + if (this.fillatt && this.fillatt.used) res.color2 = this.fillatt.color; + + if (!islines) { + res.color1 = JSROOT.Painter.root_colors[this.GetObject().fMarkerColor]; + if (!res.color2) res.color2 = res.color1; + } + + if (ttbin.empty()) + ttbin = this.draw_g.append("svg:g") + .attr("class","tooltip_bin"); + + var gry1, gry2; + + if ((this.optionEF > 0) && islines) { + gry1 = pmain.gry(bestbin.y - bestbin.eylow); + gry2 = pmain.gry(bestbin.y + bestbin.eyhigh); + } else { + gry1 = gry2 = pmain.gry(bestbin.y); + } + + res.exact = (Math.abs(pnt.x - res.x) <= radius) && + ((Math.abs(pnt.y - gry1) <= radius) || (Math.abs(pnt.y - gry2) <= radius)); + + res.menu = res.exact; + res.menu_dist = Math.sqrt((pnt.x-res.x)*(pnt.x-res.x) + Math.pow(Math.min(Math.abs(pnt.y-gry1),Math.abs(pnt.y-gry2)),2)); + + res.changed = ttbin.property("current_bin") !== bestbin; + + if (res.changed) { + ttbin.selectAll("*").remove(); // first delete all childs + ttbin.property("current_bin", bestbin); + + if (ismark) { + ttbin.append("svg:rect") + .attr("class","h1bin") + .style("pointer-events","none") + .style("opacity", "0.3") + .attr("x", (res.x - radius).toFixed(1)) + .attr("y", (res.y - radius).toFixed(1)) + .attr("width", (2*radius).toFixed(1)) + .attr("height", (2*radius).toFixed(1)); + } else { + ttbin.append("svg:circle").attr("cy", gry1.toFixed(1)) + if (Math.abs(gry1-gry2) > 1) + ttbin.append("svg:circle").attr("cy", gry2.toFixed(1)); + + var elem = ttbin.selectAll("circle") + .attr("r", radius) + .attr("cx", res.x.toFixed(1)); + + if (!islines) { + elem.style('stroke', res.color1 == 'black' ? 'green' : 'black').style('fill','none'); + } else { + if (this.optionLine) + elem.call(this.lineatt.func); + else + elem.style('stroke','black'); + if (this.optionFill > 0) + elem.call(this.fillatt.func); + else + elem.style('fill','none'); + } + } + } + + return res; + } + + JSROOT.TGraphPainter.prototype.UpdateObject = function(obj) { + if (!this.MatchObjectType(obj)) return false; + + // if our own histogram was used as axis drawing, we need update histogram as well + if (this.ownhisto) + this.main_painter().UpdateObject(obj.fHistogram); + + var graph = this.GetObject(); + // TODO: make real update of TGraph object content + graph.fX = obj.fX; + graph.fY = obj.fY; + graph.fNpoints = obj.fNpoints; + this.CreateBins(); + return true; + } + + JSROOT.TGraphPainter.prototype.CanZoomIn = function(axis,min,max) { + // allow to zoom TGraph only when at least one point in the range + + var gr = this.GetObject(); + if ((gr===null) || (axis!=="x")) return false; + + for (var n=0; n < gr.fNpoints; ++n) + if ((min < gr.fX[n]) && (gr.fX[n] < max)) return true; + + return false; + } + + JSROOT.TGraphPainter.prototype.ButtonClick = function(funcname) { + + if (funcname !== "ToggleZoom") return false; + + var main = this.main_painter(); + if (main === null) return false; + + if ((this.xmin===this.xmax) && (this.ymin = this.ymax)) return false; + + main.Zoom(this.xmin, this.xmax, this.ymin, this.ymax); + + return true; + } + + + JSROOT.TGraphPainter.prototype.DrawNextFunction = function(indx, callback) { + // method draws next function from the functions list + + var graph = this.GetObject(); + + if ((graph.fFunctions === null) || (indx >= graph.fFunctions.arr.length)) + return JSROOT.CallBack(callback); + + var func = graph.fFunctions.arr[indx]; + var opt = graph.fFunctions.opt[indx]; + + var painter = JSROOT.draw(this.divid, func, opt); + if (painter) return painter.WhenReady(this.DrawNextFunction.bind(this, indx+1, callback)); + + this.DrawNextFunction(indx+1, callback); + } + + JSROOT.Painter.drawGraph = function(divid, graph, opt) { + JSROOT.extend(this, new JSROOT.TGraphPainter(graph)); + + this.CreateBins(); + + this.SetDivId(divid, -1); // just to get access to existing elements + + if (this.main_painter() == null) { + if (graph.fHistogram == null) + graph.fHistogram = this.CreateHistogram(); + JSROOT.Painter.drawHistogram1D(divid, graph.fHistogram, "AXIS"); + this.ownhisto = true; + } + + this.SetDivId(divid); + this.DecodeOptions(opt); + this.DrawBins(); + + this.DrawNextFunction(0, this.DrawingReady.bind(this)); + + return this; + } + + // ============================================================= + + JSROOT.Painter.drawMultiGraph = function(divid, mgraph, opt) { + // function call with bind(painter) + + this.firstpainter = null; + this.autorange = false; + this.painters = []; // keep painters to be able update objects + + this.SetDivId(divid, -1); // it may be no element to set divid + + this.UpdateObject = function(obj) { + if (!this.MatchObjectType(obj)) return false; + + var mgraph = this.GetObject(), + graphs = obj.fGraphs; + + mgraph.fTitle = obj.fTitle; + + var isany = false; + if (this.firstpainter) { + var histo = obj.fHistogram; + if (this.autorange && (histo == null)) + histo = this.ScanGraphsRange(graphs); + if (this.firstpainter.UpdateObject(histo)) isany = true; + } + + for (var i = 0; i < graphs.arr.length; ++i) { + if (i= 0) + minimum = 0; + if (maximum > 0 && rw.ymax <= 0) + maximum = 0; + } + + if (uxmin < 0 && rw.xmin >= 0) { + if (logx) uxmin = 0.9 * rw.xmin; + else uxmin = 0; + } + if (uxmax > 0 && rw.xmax <= 0) { + if (logx) uxmax = 1.1 * rw.xmax; + else uxmax = 0; + } + + if (mgraph.fMinimum != -1111) + rw.ymin = minimum = mgraph.fMinimum; + if (mgraph.fMaximum != -1111) + rw.ymax = maximum = mgraph.fMaximum; + + if (minimum < 0 && rw.ymin >= 0) { + if (logy) minimum = 0.9 * rw.ymin; + } + if (maximum > 0 && rw.ymax <= 0) { + if (logy) maximum = 1.1 * rw.ymax; + } + if (minimum <= 0 && logy) + minimum = 0.001 * maximum; + if (uxmin <= 0 && logx) { + if (uxmax > 1000) + uxmin = 1; + else + uxmin = 0.001 * uxmax; + } + + // Create a temporary histogram to draw the axis (if necessary) + if (!histo) { + histo = JSROOT.Create("TH1I"); + histo.fTitle = mgraph.fTitle; + histo.fXaxis.fXmin = uxmin; + histo.fXaxis.fXmax = uxmax; + } + + histo.fYaxis.fXmin = minimum; + histo.fYaxis.fXmax = maximum; + + return histo; + } + + this.DrawAxis = function() { + // draw special histogram + + var mgraph = this.GetObject(); + + var histo = this.ScanGraphsRange(mgraph.fGraphs, mgraph.fHistogram, this.root_pad()); + + // histogram painter will be first in the pad, will define axis and + // interactive actions + this.firstpainter = JSROOT.Painter.drawHistogram1D(this.divid, histo, "AXIS"); + } + + this.DrawNextFunction = function(indx, callback) { + // method draws next function from the functions list + + var mgraph = this.GetObject(); + + if ((mgraph.fFunctions == null) || (indx >= mgraph.fFunctions.arr.length)) + return JSROOT.CallBack(callback); + + var func = mgraph.fFunctions.arr[indx]; + var opt = mgraph.fFunctions.opt[indx]; + + var painter = JSROOT.draw(this.divid, func, opt); + if (painter) return painter.WhenReady(this.DrawNextFunction.bind(this, indx+1, callback)); + + this.DrawNextFunction(indx+1, callback); + } + + this.DrawNextGraph = function(indx, opt) { + var graphs = this.GetObject().fGraphs; + + // at the end of graphs drawing draw functions (if any) + if (indx >= graphs.arr.length) + return this.DrawNextFunction(0, this.DrawingReady.bind(this)); + + var drawopt = graphs.opt[indx]; + if ((drawopt==null) || (drawopt == "")) drawopt = opt; + var subp = JSROOT.draw(this.divid, graphs.arr[indx], drawopt); + this.painters.push(subp); + subp.WhenReady(this.DrawNextGraph.bind(this, indx+1, opt)); + } + + if (opt == null) opt = ""; + opt = opt.toUpperCase().replace("3D","").replace("FB",""); // no 3D supported, FB not clear + + if ((opt.indexOf("A") >= 0) || (this.main_painter()==null)) { + opt = opt.replace("A",""); + this.DrawAxis(); + } + this.SetDivId(divid); + + this.DrawNextGraph(0, opt); + + return this; + } + + // ============================================================================== + + JSROOT.Painter.drawLegend = function(divid, obj, opt) { + + JSROOT.extend(this, new JSROOT.TPavePainter(obj)); + + this.SetDivId(divid); + + this.DrawLegendItems = function(w, h) { + + var legend = this.GetObject(), + nlines = legend.fPrimitives.arr.length, + ncols = legend.fNColumns, + nrows = nlines; + + if (ncols<2) ncols = 1; else { while ((nrows-1)*ncols >= nlines) nrows--; } + + this.StartTextDrawing(legend.fTextFont, h / (nlines * 1.2)); + + var tcolor = JSROOT.Painter.root_colors[legend.fTextColor], + column_width = Math.round(w/ncols), + padding_x = Math.round(0.03*w/ncols), + padding_y = Math.round(0.03*h), + step_y = (h - 2*padding_y)/nrows, + any_opt = false; + + for (var i = 0; i < nlines; ++i) { + var leg = legend.fPrimitives.arr[i], + lopt = leg.fOption.toLowerCase(), + icol = i % ncols, irow = (i - icol) / ncols, + x0 = icol * column_width, + tpos_x = x0 + Math.round(legend.fMargin*column_width), + pos_y = Math.round(padding_y + irow*step_y), // top corner + mid_y = Math.round(padding_y + (irow+0.5)*step_y), // center line + o_fill = leg, o_marker = leg, o_line = leg, + mo = leg.fObject, + painter = null, + isany = false; + + if ((mo !== null) && (typeof mo == 'object')) { + if ('fLineColor' in mo) o_line = mo; + if ('fFillColor' in mo) o_fill = mo; + if ('fMarkerColor' in mo) o_marker = mo; + + painter = this.FindPainterFor(mo); + } + + // Draw fill pattern (in a box) + if (lopt.indexOf('f') != -1) { + var fillatt = (painter && painter.fillatt) ? painter.fillatt : this.createAttFill(o_fill); + // box total height is yspace*0.7 + // define x,y as the center of the symbol for this entry + this.draw_g.append("svg:rect") + .attr("x", x0 + padding_x) + .attr("y", Math.round(pos_y+step_y*0.1)) + .attr("width", tpos_x - 2*padding_x - x0) + .attr("height", Math.round(step_y*0.8)) + .call(fillatt.func); + if (fillatt.color !== 'none') isany = true; + } + + // Draw line + if (lopt.indexOf('l') != -1) { + var lineatt = (painter && painter.lineatt) ? painter.lineatt : JSROOT.Painter.createAttLine(o_line) + this.draw_g.append("svg:line") + .attr("x1", x0 + padding_x) + .attr("y1", mid_y) + .attr("x2", tpos_x - padding_x) + .attr("y2", mid_y) + .call(lineatt.func); + if (lineatt.color !== 'none') isany = true; + } + + // Draw error + if (lopt.indexOf('e') != -1 && (lopt.indexOf('l') == -1 || lopt.indexOf('f') != -1)) { + } + + // Draw Polymarker + if (lopt.indexOf('p') != -1) { + var marker = (painter && painter.markeratt) ? painter.markeratt : JSROOT.Painter.createAttMarker(o_marker); + this.draw_g + .append("svg:path") + .attr("d", marker.create((x0 + tpos_x)/2, mid_y)) + .call(marker.func); + if (marker.color !== 'none') isany = true; + } + + // special case - nothing draw, try to show rect with line attributes + if (!isany && painter && painter.lineatt && (painter.lineatt.color !== 'none')) + this.draw_g.append("svg:rect") + .attr("x", x0 + padding_x) + .attr("y", Math.round(pos_y+step_y*0.1)) + .attr("width", tpos_x - 2*padding_x - x0) + .attr("height", Math.round(step_y*0.8)) + .attr("fill", "none") + .call(painter.lineatt.func); + + var pos_x = tpos_x; + if (lopt.length>0) any_opt = true; + else if (!any_opt) pos_x = x0 + padding_x; + + this.DrawText("start", pos_x, pos_y, x0+column_width-pos_x-padding_x, step_y, leg.fLabel, tcolor); + } + + // rescale after all entries are shown + this.FinishTextDrawing(); + } + + this.PaveDrawFunc = this.DrawLegendItems; + + this.Redraw(); + + return this.DrawingReady(); + } + + // =========================================================================== + + JSROOT.Painter.drawPaletteAxis = function(divid,palette,opt) { + + // disable draw of shadow element of TPave + palette.fBorderSize = 1; + palette.fShadowColor = 0; + + JSROOT.extend(this, new JSROOT.TPavePainter(palette)); + + this.SetDivId(divid); + + this.z_handle = new JSROOT.TAxisPainter(palette.fAxis, true); + this.z_handle.SetDivId(divid, -1); + + this.DrawAxisPalette = function(s_width, s_height, arg) { + + var pthis = this, + palette = this.GetObject(), + axis = palette.fAxis, + can_move = (typeof arg == 'string') && (arg.indexOf('canmove')>0), + postpone_draw = (typeof arg == 'string') && (arg.indexOf('postpone')>0); + + var nbr1 = axis.fNdiv % 100; + if (nbr1<=0) nbr1 = 8; + + var pos_x = parseInt(this.draw_g.attr("x")), // pave position + pos_y = parseInt(this.draw_g.attr("y")), + width = this.pad_width(), + height = this.pad_height(), + axisOffset = axis.fLabelOffset * width, + main = this.main_painter(), + zmin = 0, zmax = 100, + contour = main.fContour; + + axis.fTickSize = 0.6 * s_width / width; // adjust axis ticks size + + if (contour) { + zmin = contour[0]; zmax = contour[contour.length-1]; + } else + if ((main.gmaxbin!==undefined) && (main.gminbin!==undefined)) { + // this is case of TH2 (needs only for size adjustment) + zmin = main.gminbin; zmax = main.gmaxbin; + } else + if ((main.hmin!==undefined) && (main.hmax!==undefined)) { + // this is case of TH1 + zmin = main.hmin; zmax = main.hmax; + } + + var z = null, z_kind = "normal"; + + if (this.root_pad().fLogz) { + z = d3.scale.log(); + z_kind = "log"; + } else { + z = d3.scale.linear(); + } + z.domain([zmin, zmax]).range([s_height,0]); + + if (!contour || postpone_draw) + // we need such rect to correctly calculate size + this.draw_g.append("svg:rect") + .attr("x", 0) + .attr("y", 0) + .attr("width", s_width) + .attr("height", s_height) + .attr("fill", 'white'); + else + for (var i=0;i 0) + r.on('mouseover', function() { + d3.select(this).transition().duration(100).style("fill", d3.select(this).property('fill1')); + }).on('mouseout', function() { + d3.select(this).transition().duration(100).style("fill", d3.select(this).property('fill0')); + }).append("svg:title").text(contour[i].toFixed(2) + " - " + contour[i+1].toFixed(2)); + + if (JSROOT.gStyle.Zooming) + r.on("dblclick", function() { pthis.main_painter().Unzoom("z"); }); + } + + + this.z_handle.SetAxisConfig("zaxis", z_kind, z, zmin, zmax, zmin, zmax); + + this.z_handle.DrawAxis(true, this.draw_g, s_width, s_height, "translate(" + s_width + ", 0)"); + + if (can_move && ('getBoundingClientRect' in this.draw_g.node())) { + var rect = this.draw_g.node().getBoundingClientRect(); + + var shift = (pos_x + parseInt(rect.width)) - Math.round(0.995*width) + 3; + + if (shift>0) { + this.draw_g.attr("x", pos_x - shift).attr("y", pos_y) + .attr("transform", "translate(" + (pos_x-shift) + ", " + pos_y + ")"); + palette.fX1NDC -= shift/width; + palette.fX2NDC -= shift/width; + } + } + + if (!JSROOT.gStyle.Zooming) return; + + var evnt = null, doing_zoom = false, sel1 = 0, sel2 = 0, zoom_rect = null; + + function moveRectSel() { + + if (!doing_zoom) return; + + d3.event.preventDefault(); + var m = d3.mouse(evnt); + + if (m[1] < sel1) sel1 = m[1]; else sel2 = m[1]; + + zoom_rect.attr("y", sel1) + .attr("height", Math.abs(sel2-sel1)); + } + + function endRectSel() { + if (!doing_zoom) return; + + d3.event.preventDefault(); + d3.select(window).on("mousemove.colzoomRect", null) + .on("mouseup.colzoomRect", null); + zoom_rect.remove(); + zoom_rect = null; + doing_zoom = false; + + var zmin = Math.min(z.invert(sel1), z.invert(sel2)), + zmax = Math.max(z.invert(sel1), z.invert(sel2)); + + pthis.main_painter().Zoom(undefined, undefined, undefined, undefined, zmin, zmax); + } + + function startRectSel() { + // ignore when touch selection is actiavated + if (doing_zoom) return; + doing_zoom = true; + + d3.event.preventDefault(); + + evnt = this; + var origin = d3.mouse(evnt); + + sel1 = sel2 = origin[1]; + + zoom_rect = pthis.draw_g + .append("svg:rect") + .attr("class", "zoom") + .attr("id", "colzoomRect") + .attr("x", "0") + .attr("width", s_width) + .attr("y", sel1) + .attr("height", 5); + + d3.select(window).on("mousemove.colzoomRect", moveRectSel) + .on("mouseup.colzoomRect", endRectSel, true); + + d3.event.stopPropagation(); + } + + this.draw_g.select(".axis_zoom") + .on("mousedown", startRectSel) + .on("dblclick", function() { pthis.main_painter().Unzoom("z"); }); + } + + this.ShowContextMenu = function(evnt) { + this.main_painter().ShowContextMenu("z", evnt, this.GetObject().fAxis); + } + +// this.Redraw = function() { + //this.Enabled = true; +// var main = this.main_painter(); +// this.UseContextMenu = (main !== null); +// if ((main !== null) && main.options) +// this.Enabled = (main.options.Zscale > 0) && +// ((main.options.Color > 0) || (main.options.Lego === 12) || (main.options.Lego === 14)); +// +// this.DrawPave(); +// } + + this.PaveDrawFunc = this.DrawAxisPalette; + + // workaround to let copmlete pallete draw when actual palette colors already there + // this.CompleteDraw = this.Redraw; + + this.UseContextMenu = true; + + this.DrawPave(opt); + + return this.DrawingReady(); + } + + // ================= some functions for basic histogram painter ======================= + + JSROOT.THistPainter.prototype.CreateContour = function(nlevels, zmin, zmax, zminpositive) { + + if (nlevels<1) nlevels = 20; + this.fContour = []; + this.zmin = zmin; + this.zmax = zmax; + + if (this.root_pad().fLogz) { + if (this.zmax <= 0) this.zmax = 1.; + if (this.zmin <= 0) + this.zmin = (zminpositive!==undefined) && (zminpositive > 0) ? 0.3*zminpositive : 0.0001*this.zmax; + if (this.zmin >= this.zmax) this.zmin = 0.0001*this.zmax; + + var logmin = Math.log(this.zmin)/Math.log(10); + var logmax = Math.log(this.zmax)/Math.log(10); + var dz = (logmax-logmin)/nlevels; + this.fContour.push(this.zmin); + for (var level=1; level1) && histo.TestBit(JSROOT.TH1StatusBits.kUserContour)) { + this.fContour = JSROOT.clone(histo.fContour); + this.fCustomContour = true; + } else { + var nlevels = 20, zmin = this.minbin, zmax = this.maxbin; + if (histo.fContour != null) nlevels = histo.fContour.length; + if ((this.histo.fMinimum != -1111) && (this.histo.fMaximum != -1111)) { + zmin = this.histo.fMinimum; + zmax = this.histo.fMaximum; + } + if (this.zoom_zmin != this.zoom_zmax) { + zmin = this.zoom_zmin; + zmax = this.zoom_zmax; + } + this.CreateContour(nlevels, zmin, zmax, this.minposbin); + } + } + + if (this.fCustomContour) { + var cntr = this.fContour, l = 0, r = this.fContour.length-1, mid; + if (zc < cntr[0]) return -1; + if (zc >= cntr[r]) return r; + while (l < r-1) { + mid = Math.round((l+r)/2); + if (cntr[mid] > zc) r = mid; else l = mid; + } + return l; + } + + // bins less than zmin not drawn + if (zc < this.zmin) return -111; + + // if bin content exactly zmin, draw it when col0 specified or when content is positive + if (zc===this.zmin) return ((this.zmin > 0) || (this.options.Color === 111)) ? 0 : -1; + + return Math.floor(0.01+(zc-this.zmin)*(this.fContour.length-1)/(this.zmax-this.zmin)); + } + + + JSROOT.THistPainter.prototype.getValueColor = function(zc, asindx) { + + var index = this.getContourIndex(zc); + + if (index < 0) return null; + + var palette = this.GetPalette(); + + var theColor = Math.floor((index+0.99)*palette.length/(this.fContour.length-1)); + if (theColor > palette.length-1) theColor = palette.length-1; + return asindx ? theColor : palette[theColor]; + } + + JSROOT.THistPainter.prototype.GetPalette = function(force) { + if (!this.fPalette || force) + this.fPalette = JSROOT.Painter.GetColorPalette(this.options.Palette); + return this.fPalette; + } + + JSROOT.THistPainter.prototype.FillPaletteMenu = function(menu) { + + var curr = this.options.Palette; + if ((curr===null) || (curr===0)) curr = JSROOT.gStyle.Palette; + + function change(arg) { + this.options.Palette = parseInt(arg); + this.GetPalette(true); + this.Redraw(); // redraw histogram + }; + + function add(id, name, more) { + menu.addchk((id===curr) || more, '' + name + '', id, change); + }; + + menu.add("sub:Palette"); + + add(50, "ROOT 5", (curr>=10) && (curr<51)); + add(51, "Deep Sea"); + add(52, "Grayscale", (curr>0) && (curr<10)); + add(53, "Dark body radiator"); + add(54, "Two-color hue"); + add(55, "Rainbow"); + add(56, "Inverted dark body radiator"); + add(57, "Bird", (curr>112)); + add(58, "Cubehelix"); + add(59, "Green Red Violet"); + add(60, "Blue Red Yellow"); + add(61, "Ocean"); + add(62, "Color Printable On Grey"); + add(63, "Alpine"); + add(64, "Aquamarine"); + add(65, "Army"); + add(66, "Atlantic"); + + menu.add("endsub:"); + } + + JSROOT.THistPainter.prototype.DrawColorPalette = function(enabled, postpone_draw, can_move) { + // only when create new palette, one could change frame size + + var pal = this.FindFunction('TPaletteAxis'), + pal_painter = this.FindPainterFor(pal); + + if (this._can_move_colz) { can_move = true; delete this._can_move_colz; } + + if (!pal_painter && !pal) { + pal_painter = this.FindPainterFor(undefined, undefined, "TPaletteAxis"); + if (pal_painter) { + pal = pal_painter.GetObject(); + // add to list of functions + this.AddFunction(pal, true); + } + } + + if (!enabled) { + if (pal_painter) { + pal_painter.Enabled = false; + pal_painter.RemoveDrawG(); // completely remove drawing without need to redraw complete pad + } + + return null; + } + + if (pal === null) { + pal = JSROOT.Create('TPave'); + + JSROOT.extend(pal, { _typename: "TPaletteAxis", fName: "TPave", fH: null, fAxis: null, + fX1NDC: 0.91, fX2NDC: 0.95, fY1NDC: 0.1, fY2NDC: 0.9, fInit: 1 } ); + + pal.fAxis = JSROOT.Create('TGaxis'); + + // set values from base classes + + JSROOT.extend(pal.fAxis, { fTitle: this.GetObject().fZaxis.fTitle, + fLineColor: 1, fLineSyle: 1, fLineWidth: 1, + fTextAngle: 0, fTextSize: 0.04, fTextAlign: 11, fTextColor: 1, fTextFont: 42 }); + + // place colz in the beginning, that stat box is always drawn on the top + this.AddFunction(pal, true); + + can_move = true; + } + + var frame_painter = this.frame_painter(); + + // keep palette width + if (can_move) { + pal.fX2NDC = frame_painter.fX2NDC + 0.01 + (pal.fX2NDC - pal.fX1NDC); + pal.fX1NDC = frame_painter.fX2NDC + 0.01; + pal.fY1NDC = frame_painter.fY1NDC; + pal.fY2NDC = frame_painter.fY2NDC; + } + + var arg = ""; + if (postpone_draw) arg+=";postpone"; + if (can_move && !this.do_redraw_palette) arg+= ";canmove" + + if (pal_painter === null) { + // when histogram drawn on sub pad, let draw new axis object on the same pad + var prev = this.CurrentPadName(this.pad_name); + pal_painter = JSROOT.draw(this.divid, pal, arg); + this.CurrentPadName(prev); + } else { + pal_painter.Enabled = true; + pal_painter.DrawPave(arg); + } + + // make dummy redraw, palette will be updated only from histogram painter + pal_painter.Redraw = function() {}; + + if ((pal.fX1NDC-0.005 < frame_painter.fX2NDC) && !this.do_redraw_palette && can_move) { + + this.do_redraw_palette = true; + + frame_painter.fX2NDC = pal.fX1NDC - 0.01; + frame_painter.Redraw(); + // here we should redraw main object + if (!postpone_draw) this.Redraw(); + + delete this.do_redraw_palette; + } + + return pal_painter; + } + + JSROOT.THistPainter.prototype.ToggleColz = function() { + if (this.options.Zscale > 0) { + this.options.Zscale = 0; + } else { + this.options.Zscale = 1; + } + + this.DrawColorPalette(this.options.Zscale > 0, false, true); + } + + + // ==================== painter for TH2 histograms ============================== + + JSROOT.TH2Painter = function(histo) { + JSROOT.THistPainter.call(this, histo); + this.fContour = null; // contour levels + this.fCustomContour = false; // are this user-defined levels (can be irregular) + this.fPalette = null; + } + + JSROOT.TH2Painter.prototype = Object.create(JSROOT.THistPainter.prototype); + + JSROOT.TH2Painter.prototype.FillHistContextMenu = function(menu) { + // painter automatically bind to menu callbacks + menu.add("Auto zoom-in", this.AutoZoom); + + menu.addDrawMenu("Draw with", ["col", "colz", "scat", "box", "text", "lego", "lego0", "lego1", "lego2", "lego3", "lego4"], function(arg) { + this.options = this.DecodeOptions(arg); + + this.Redraw(); + + // if (this.options.Lego == 0) this.AddInteractive(); + }); + + if (this.options.Color > 0) + this.FillPaletteMenu(menu); + } + + JSROOT.TH2Painter.prototype.ButtonClick = function(funcname) { + if (JSROOT.THistPainter.prototype.ButtonClick.call(this, funcname)) return true; + + if (this !== this.main_painter()) return false; + + switch(funcname) { + case "ToggleColor": this.ToggleColor(); break; + case "ToggleColorZ": + if (this.options.Lego === 12 || this.options.Lego === 14 || this.options.Color > 0) this.ToggleColz(); + break; + case "Toggle3D": + if (this.options.Lego > 0) { + this.options.Lego = 0; + } else { + if ((this.nbinsx>=50) || (this.nbinsy>=50)) + this.options.Lego = (this.options.Color > 0) ? 14 : 13; + else + this.options.Lego = (this.options.Color > 0) ? 12 : 1; + + this.options.Zero = 1; + } + + this.RedrawPad(); + break; + default: return false; + } + + // all methods here should not be processed further + return true; + } + + JSROOT.TH2Painter.prototype.FillToolbar = function() { + JSROOT.THistPainter.prototype.FillToolbar.call(this); + + var pp = this.pad_painter(true); + if (pp===null) return; + + pp.AddButton(JSROOT.ToolbarIcons.th2color, "Toggle color", "ToggleColor"); + pp.AddButton(JSROOT.ToolbarIcons.th2colorz, "Toggle color palette", "ToggleColorZ"); + pp.AddButton(JSROOT.ToolbarIcons.th2draw3d, "Toggle 3D mode", "Toggle3D"); + } + + JSROOT.TH2Painter.prototype.ToggleColor = function() { + + var toggle = true; + + if (this.options.Lego > 0) { this.options.Lego = 0; toggle = false; } + + if (this.options.Color == 0) { + this.options.Color = ('LastColor' in this.options) ? this.options.LastColor : 1; + } else + if (toggle) { + this.options.LastColor = this.options.Color; + this.options.Color = 0; + } + + this._can_move_colz = true; // indicate that next redraw can move Z scale + + this.Redraw(); + + // this.DrawColorPalette((this.options.Color > 0) && (this.options.Zscale > 0)); + } + + JSROOT.TH2Painter.prototype.AutoZoom = function() { + var i1 = this.GetSelectIndex("x", "left", -1), + i2 = this.GetSelectIndex("x", "right", 1), + j1 = this.GetSelectIndex("y", "left", -1), + j2 = this.GetSelectIndex("y", "right", 1), + i,j, histo = this.GetObject(); + + if ((i1 == i2) || (j1 == j2)) return; + + // first find minimum + var min = histo.getBinContent(i1 + 1, j1 + 1); + for (i = i1; i < i2; ++i) + for (j = j1; j < j2; ++j) + if (histo.getBinContent(i + 1, j + 1) < min) + min = histo.getBinContent(i + 1, j + 1); + if (min>0) return; // if all points positive, no chance for autoscale + + var ileft = i2, iright = i1, jleft = j2, jright = j1; + + for (i = i1; i < i2; ++i) + for (j = j1; j < j2; ++j) + if (histo.getBinContent(i + 1, j + 1) > min) { + if (i < ileft) ileft = i; + if (i >= iright) iright = i + 1; + if (j < jleft) jleft = j; + if (j >= jright) jright = j + 1; + } + + var xmin, xmax, ymin, ymax, isany = false; + + if ((ileft > i1 || iright < i2) && (ileft < iright - 1)) { + xmin = this.GetBinX(ileft); + xmax = this.GetBinX(iright); + isany = true; + } + + if ((jleft > j1 || jright < j2) && (jleft < jright - 1)) { + ymin = this.GetBinY(jleft); + ymax = this.GetBinY(jright); + isany = true; + } + + if (isany) this.Zoom(xmin, xmax, ymin, ymax); + } + + + JSROOT.TH2Painter.prototype.ScanContent = function() { + var i,j,histo = this.GetObject(); + + this.nbinsx = histo.fXaxis.fNbins; + this.nbinsy = histo.fYaxis.fNbins; + + // used in CreateXY method + + this.CreateAxisFuncs(true); + + // global min/max, used at the moment in 3D drawing + this.gminbin = this.gmaxbin = histo.getBinContent(1, 1); + this.gmin0bin = null; + for (i = 0; i < this.nbinsx; ++i) { + for (j = 0; j < this.nbinsy; ++j) { + var bin_content = histo.getBinContent(i+1, j+1); + if (bin_content < this.gminbin) this.gminbin = bin_content; else + if (bin_content > this.gmaxbin) this.gmaxbin = bin_content; + if (bin_content > 0) + if ((this.gmin0bin===null) || (this.gmin0bin > bin_content)) this.gmin0bin = bin_content; + } + } + + // this value used for logz scale drawing + if (this.gmin0bin === null) this.gmin0bin = this.gmaxbin*1e-4; + + // used to enable/disable stat box + this.draw_content = this.gmaxbin > 0; + + // apply selected user X range if no other range selection was done + if (this.is_main_painter() && (this.zoom_xmin === this.zoom_xmax) && + this.histo.fXaxis.TestBit(JSROOT.EAxisBits.kAxisRange) && + (this.histo.fXaxis.fFirst !== this.histo.fXaxis.fLast) && + ((this.histo.fXaxis.fFirst>1) || (this.histo.fXaxis.fLast <= this.nbinsx))) { + this.zoom_xmin = this.histo.fXaxis.fFirst > 1 ? this.GetBinX(this.histo.fXaxis.fFirst-1) : this.xmin; + this.zoom_xmax = this.histo.fXaxis.fLast <= this.nbinsx ? this.GetBinX(this.histo.fXaxis.fLast) : this.xmax; + } + + // apply selected user Y range if no other range selection was done + if (this.is_main_painter() && (this.zoom_ymin === this.zoom_ymax) && + this.histo.fYaxis.TestBit(JSROOT.EAxisBits.kAxisRange) && + (this.histo.fYaxis.fFirst !== this.histo.fYaxis.fLast) && + ((this.histo.fYaxis.fFirst>1) || (this.histo.fYaxis.fLast <= this.nbinsy))) { + this.zoom_ymin = this.histo.fYaxis.fFirst > 1 ? this.GetBinY(this.histo.fYaxis.fFirst-1) : this.ymin; + this.zoom_ymax = this.histo.fYaxis.fLast <= this.nbinsy ? this.GetBinY(this.histo.fYaxis.fLast) : this.ymax; + } + } + + JSROOT.TH2Painter.prototype.CountStat = function(cond) { + var histo = this.GetObject(), + stat_sum0 = 0, stat_sumx1 = 0, stat_sumy1 = 0, + stat_sumx2 = 0, stat_sumy2 = 0, stat_sumxy = 0, + xleft = this.GetSelectIndex("x", "left"), + xright = this.GetSelectIndex("x", "right"), + yleft = this.GetSelectIndex("y", "left"), + yright = this.GetSelectIndex("y", "right"), + xi, xside, xx, yi, yside, yy, zz, + res = { entries: 0, integral: 0, meanx: 0, meany: 0, rmsx: 0, rmsy: 0, matrix: [0,0,0,0,0,0,0,0,0], xmax: 0, ymax:0, wmax: null }; + + for (xi = 0; xi <= this.nbinsx + 1; ++xi) { + xside = (xi <= xleft) ? 0 : (xi > xright ? 2 : 1); + xx = this.GetBinX(xi - 0.5); + + for (yi = 0; yi <= this.nbinsy + 1; ++yi) { + yside = (yi <= yleft) ? 0 : (yi > yright ? 2 : 1); + yy = this.GetBinY(yi - 0.5); + + zz = histo.getBinContent(xi, yi); + + res.entries += zz; + + res.matrix[yside * 3 + xside] += zz; + + if ((xside != 1) || (yside != 1)) continue; + + if ((cond!=null) && !cond(xx,yy)) continue; + + if ((res.wmax==null) || (zz>res.wmax)) { res.wmax = zz; res.xmax = xx; res.ymax = yy; } + + stat_sum0 += zz; + stat_sumx1 += xx * zz; + stat_sumy1 += yy * zz; + stat_sumx2 += xx * xx * zz; + stat_sumy2 += yy * yy * zz; + stat_sumxy += xx * yy * zz; + } + } + + if (!this.IsAxisZoomed("x") && !this.IsAxisZoomed("y") && (histo.fTsumw > 0)) { + stat_sum0 = histo.fTsumw; + stat_sumx1 = histo.fTsumwx; + stat_sumx2 = histo.fTsumwx2; + stat_sumy1 = histo.fTsumwy; + stat_sumy2 = histo.fTsumwy2; + stat_sumxy = histo.fTsumwxy; + } + + if (stat_sum0 > 0) { + res.meanx = stat_sumx1 / stat_sum0; + res.meany = stat_sumy1 / stat_sum0; + res.rmsx = Math.sqrt(stat_sumx2 / stat_sum0 - res.meanx * res.meanx); + res.rmsy = Math.sqrt(stat_sumy2 / stat_sum0 - res.meany * res.meany); + } + + if (res.wmax===null) res.wmax = 0; + res.integral = stat_sum0; + + if (histo.fEntries > 1) res.entries = histo.fEntries; + + return res; + } + + JSROOT.TH2Painter.prototype.FillStatistic = function(stat, dostat, dofit) { + if (this.GetObject() === null) return false; + + var pave = stat.GetObject(), + data = this.CountStat(), + print_name = Math.floor(dostat % 10), + print_entries = Math.floor(dostat / 10) % 10, + print_mean = Math.floor(dostat / 100) % 10, + print_rms = Math.floor(dostat / 1000) % 10, + print_under = Math.floor(dostat / 10000) % 10, + print_over = Math.floor(dostat / 100000) % 10, + print_integral = Math.floor(dostat / 1000000) % 10, + print_skew = Math.floor(dostat / 10000000) % 10, + print_kurt = Math.floor(dostat / 100000000) % 10; + + if (print_name > 0) + pave.AddText(this.GetObject().fName); + + if (print_entries > 0) + pave.AddText("Entries = " + stat.Format(data.entries,"entries")); + + if (print_mean > 0) { + pave.AddText("Mean x = " + stat.Format(data.meanx)); + pave.AddText("Mean y = " + stat.Format(data.meany)); + } + + if (print_rms > 0) { + pave.AddText("Std Dev x = " + stat.Format(data.rmsx)); + pave.AddText("Std Dev y = " + stat.Format(data.rmsy)); + } + + if (print_integral > 0) { + pave.AddText("Integral = " + stat.Format(data.matrix[4],"entries")); + } + + if (print_skew > 0) { + pave.AddText("Skewness x = "); + pave.AddText("Skewness y = "); + } + + if (print_kurt > 0) + pave.AddText("Kurt = "); + + if ((print_under > 0) || (print_over > 0)) { + var m = data.matrix; + + pave.AddText("" + m[6].toFixed(0) + " | " + m[7].toFixed(0) + " | " + m[7].toFixed(0)); + pave.AddText("" + m[3].toFixed(0) + " | " + m[4].toFixed(0) + " | " + m[5].toFixed(0)); + pave.AddText("" + m[0].toFixed(0) + " | " + m[1].toFixed(0) + " | " + m[2].toFixed(0)); + } + + // adjust the size of the stats box wrt the number of lines + var nlines = pave.fLines.arr.length, + stath = nlines * JSROOT.gStyle.StatFontSize; + if (stath <= 0 || 3 == (JSROOT.gStyle.StatFont % 10)) { + stath = 0.25 * nlines * JSROOT.gStyle.StatH; + pave.fY1NDC = 0.93 - stath; + pave.fY2NDC = 0.93; + } + + return true; + } + + JSROOT.TH2Painter.prototype.PrepareColorDraw = function(dorounding, pixel_density) { + var histo = this.GetObject(), + pad = this.root_pad(), + pmain = this.main_painter(), + i, j, x, y, binz, binarea, + res = { + i1: this.GetSelectIndex("x", "left", 0), + i2: this.GetSelectIndex("x", "right", 1), + j1: this.GetSelectIndex("y", "left", 0), + j2: this.GetSelectIndex("y", "right", 1), + min: 0, max: 0 + }; + res.grx = new Float32Array(res.i2+1); + res.gry = new Float32Array(res.j2+1); + + if (pixel_density) dorounding = true; + + // calculate graphical coordinates in advance + for (i = res.i1; i <= res.i2; ++i) { + x = this.GetBinX(i); + if (pmain.logx && (x <= 0)) { res.i1 = i+1; continue; } + res.grx[i] = pmain.grx(x); + if (dorounding) res.grx[i] = Math.round(res.grx[i]); + } + + for (j = res.j1; j <= res.j2; ++j) { + y = this.GetBinY(j); + if (pmain.logy && (y <= 0)) { res.j1 = j+1; continue; } + res.gry[j] = pmain.gry(y); + if (dorounding) res.gry[j] = Math.round(res.gry[j]); + } + + // find min/max values in selected range + + binz = histo.getBinContent(res.i1 + 1, res.j1 + 1); + this.maxbin = this.minbin = this.minposbin = null; + + for (i = res.i1; i < res.i2; ++i) { + for (j = res.j1; j < res.j2; ++j) { + binz = histo.getBinContent(i + 1, j + 1); + if (pixel_density) { + binarea = (res.grx[i+1]-res.grx[i])*(res.gry[j]-res.gry[j+1]); + if (binarea <= 0) continue; + res.max = Math.max(res.max, binz); + if ((binz>0) && ((binz 0) + if ((this.minposbin===null) || (binz0)) { + uselogz = true; + logmax = Math.log(this.maxbin); + logmin = (this.minbin > 0) ? Math.log(this.minbin) : logmax - 10; + if (logmin >= logmax) logmin = logmax - 10; + xfactor = 0.5 / (logmax - logmin); + yfactor = 0.5 / (logmax - logmin); + } else { + xfactor = 0.5 / (this.maxbin - this.minbin); + yfactor = 0.5 / (this.maxbin - this.minbin); + } + + // now start build + for (i = handle.i1; i < handle.i2; ++i) { + for (j = handle.j1; j < handle.j2; ++j) { + binz = histo.getBinContent(i + 1, j + 1); + if ((binz == 0) || (binz < this.minbin)) continue; + + zdiff = uselogz ? (logmax - ((binz>0) ? Math.log(binz) : logmin)) : this.maxbin - binz; + + ww = handle.grx[i+1] - handle.grx[i]; + hh = handle.gry[j] - handle.gry[j+1]; + + dgrx = zdiff * xfactor * ww; + dgry = zdiff * yfactor * hh; + + ww = Math.max(Math.round(ww - 2*dgrx), 1); + hh = Math.max(Math.round(hh - 2*dgry), 1); + + if (colPaths[i]===undefined) colPaths[i] = ""; + colPaths[i] += "M" + Math.round(handle.grx[i] + dgrx) + "," + Math.round(handle.gry[j+1] + dgry) + + "v" + hh + "h" + ww + "v-" + hh + "z"; + } + } + + for (i=0;i=0.001) pnt.whiskerm = this.GetBinY(j + 0.5); // Lower whisker + if (counter/integral < 0.25 && (counter + cont)/integral >=0.25) pnt.m25y = this.GetBinY(j + 0.5); // Lower edge of box + if (counter/integral < 0.5 && (counter + cont)/integral >=0.5) pnt.median = this.GetBinY(j + 0.5); //Median + if (counter/integral < 0.75 && (counter + cont)/integral >=0.75) pnt.p25y = this.GetBinY(j + 0.5); //Uppeder edge of box + if (counter/integral < 0.999 && (counter + cont)/integral >=0.999) pnt.whiskerp = this.GetBinY(j + 0.5); // Upper whisker + counter += cont; + y = this.GetBinY(j + 0.5); // center of y bin coordinate + sum1 += cont*y; + } + if (counter > 0) { + pnt.meany = sum1/counter; + } + pnt.iqr = pnt.p25y-pnt.m25y; + +// console.log('Whisker before ' + pnt.whiskerm + '/' + pnt.whiskerp); + + //Whsikers cannot exceed 1.5*iqr from box + if ((pnt.m25y-1.5*pnt.iqr) > pnt.whsikerm) { + pnt.whiskerm = pnt.m25y-1.5*pnt.iqr; + } + if ((pnt.p25y+1.5*pnt.iqr) < pnt.whiskerp) { + pnt.whiskerp = pnt.p25y+1.5*pnt.iqr; + } +// console.log('Whisker after ' + pnt.whiskerm + '/' + pnt.whiskerp); + + // exclude points with negative y when log scale is specified + if (pmain.logy && (pnt.whiskerm<=0)) continue; + + w = handle.grx[i+1] - handle.grx[i]; + w *= 0.66; + center = (handle.grx[i+1] + handle.grx[i]) / 2 + histo.fBarOffset/1000*w; + if (histo.fBarWidth>0) w = w * histo.fBarWidth / 1000; + + pnt.x1 = Math.round(center - w/2); + pnt.x2 = Math.round(center + w/2); + center = Math.round(center); + + pnt.y0 = Math.round(pmain.gry(pnt.median)); + // mean line + bars += "M" + pnt.x1 + "," + pnt.y0 + "h" + (pnt.x2-pnt.x1); + + pnt.y1 = Math.round(pmain.gry(pnt.p25y)); + pnt.y2 = Math.round(pmain.gry(pnt.m25y)); + + // rectangle + bars += "M" + pnt.x1 + "," + pnt.y1 + + "v" + (pnt.y2-pnt.y1) + "h" + (pnt.x2-pnt.x1) + "v-" + (pnt.y2-pnt.y1) + "z"; + + pnt.yy1 = Math.round(pmain.gry(pnt.whiskerp)); + pnt.yy2 = Math.round(pmain.gry(pnt.whiskerm)); + + // upper part + bars += "M" + center + "," + pnt.y1 + "v" + (pnt.yy1-pnt.y1); + bars += "M" + pnt.x1 + "," + pnt.yy1 + "h" + (pnt.x2-pnt.x1); + + // lower part + bars += "M" + center + "," + pnt.y2 + "v" + (pnt.yy2-pnt.y2); + bars += "M" + pnt.x1 + "," + pnt.yy2 + "h" + (pnt.x2-pnt.x1); + +// console.log('Whisker-: '+ pnt.whiskerm + ' Whisker+:' + pnt.whiskerp); + //estimate outliers + for (j = 0; j < this.nbinsy; ++j) { + cont = histo.getBinContent(i+1,j+1); + if (cont > 0 && this.GetBinY(j + 0.5) < pnt.whiskerm) markers += this.markeratt.create(center, this.GetBinY(j + 0.5)); + if (cont > 0 && this.GetBinY(j + 0.5) > pnt.whiskerp) markers += this.markeratt.create(center, this.GetBinY(j + 0.5)); + } + + handle.candle.push(pnt); // keep point for the tooltip + } + + if (bars.length > 0) + this.draw_g.append("svg:path") + .attr("d", bars) + .call(this.lineatt.func) + .call(this.fillatt.func); + + if (markers.length > 0) + this.draw_g.append("svg:path") + .attr("d", markers) + .call(this.markeratt.func); + + return handle; + } + + JSROOT.TH2Painter.prototype.DrawBinsScatter = function(w,h) { + var histo = this.GetObject(), + handle = this.PrepareColorDraw(true, true), + colPaths = [], currx = [], curry = [], cell_w = [], cell_h = [], + colindx, cmd1, cmd2, i, j, binz, cw, ch, factor = 1.; + + // limit filling factor, do not try to produce as many points as filled area; + if (this.maxbin > 0.7) factor = 0.7/this.maxbin; + + var nlevels = Math.round(handle.max - handle.min); + this.CreateContour((nlevels > 50) ? 50 : nlevels, this.minposbin, this.maxbin, this.minposbin); + + // now start build + for (i = handle.i1; i < handle.i2; ++i) { + for (j = handle.j1; j < handle.j2; ++j) { + binz = histo.getBinContent(i + 1, j + 1); + if ((binz == 0) || (binz < this.minbin)) continue; + + cw = handle.grx[i+1] - handle.grx[i]; + ch = handle.gry[j] - handle.gry[j+1]; + if (cw*ch <= 0) continue; + + colindx = this.getContourIndex(binz/cw/ch); + if (colindx < 0) continue; + + cmd1 = "M"+handle.grx[i]+","+handle.gry[j+1]; + if (colPaths[colindx] === undefined) { + colPaths[colindx] = cmd1; + cell_w[colindx] = cw; + cell_h[colindx] = ch; + } else{ + cmd2 = "m" + (handle.grx[i]-currx[colindx]) + "," + (handle.gry[j+1] - curry[colindx]); + colPaths[colindx] += (cmd2.length < cmd1.length) ? cmd2 : cmd1; + cell_w[colindx] = Math.max(cell_w[colindx], cw); + cell_h[colindx] = Math.max(cell_h[colindx], ch); + } + + currx[colindx] = handle.grx[i]; + curry[colindx] = handle.gry[j+1]; + + colPaths[colindx] += "v"+ch+"h"+cw+"v-"+ch+"z"; + } + } + + var layer = this.svg_frame().select('.main_layer'); + var defs = layer.select("defs"); + if (defs.empty() && (colPaths.length>0)) + defs = layer.insert("svg:defs",":first-child"); + + if (!this.markeratt) + this.markeratt = JSROOT.Painter.createAttMarker(histo); + + for (colindx=0;colindx 0) + handle = this.DrawBinsColor(w, h); + else + if (this.options.Scat > 0) + handle = this.DrawBinsScatter(w, h); + else + if (this.options.Box > 0) + handle = this.DrawBinsBox(w, h); + else + if (this.options.Candle.length > 0) + handle = this.DrawCandle(w, h); + + if (this.options.Text > 0) + handle = this.DrawBinsText(w, h, handle); + + this.tt_handle = handle; + } + + JSROOT.TH2Painter.prototype.GetBinTips = function (i, j) { + var lines = [], pmain = this.main_painter(); + + lines.push(this.GetTipName()); + + if (this.x_kind == 'labels') + lines.push("x = " + pmain.AxisAsText("x", this.GetBinX(i))); + else + lines.push("x = [" + pmain.AxisAsText("x", this.GetBinX(i)) + ", " + pmain.AxisAsText("x", this.GetBinX(i+1)) + ")"); + + if (this.y_kind == 'labels') + lines.push("y = " + pmain.AxisAsText("y", this.GetBinY(j))); + else + lines.push("y = [" + pmain.AxisAsText("y", this.GetBinY(j)) + ", " + pmain.AxisAsText("y", this.GetBinY(j+1)) + ")"); + + lines.push("bin = " + i + ", " + j); + + var binz = this.GetObject().getBinContent(i+1,j+1); + if (binz === Math.round(binz)) + lines.push("entries = " + binz); + else + lines.push("entries = " + JSROOT.FFormat(binz, JSROOT.gStyle.StatFormat)); + + return lines; + } + + JSROOT.TH2Painter.prototype.GetCandleTips = function(p) { + var lines = [], main = this.main_painter(); + + lines.push(this.GetTipName()); + + lines.push("x = " + main.AxisAsText("x", this.GetBinX(p.bin))); + // lines.push("x = [" + main.AxisAsText("x", this.GetBinX(p.bin)) + ", " + main.AxisAsText("x", this.GetBinX(p.bin+1)) + ")"); + + lines.push('mean y = ' + JSROOT.FFormat(p.meany, JSROOT.gStyle.StatFormat)) + lines.push('m25 = ' + JSROOT.FFormat(p.m25y, JSROOT.gStyle.StatFormat)) + lines.push('p25 = ' + JSROOT.FFormat(p.p25y, JSROOT.gStyle.StatFormat)) + + return lines; + } + + JSROOT.TH2Painter.prototype.ProcessTooltip = function(pnt) { + if ((pnt==null) || !this.draw_content || !this.draw_g) { + if (this.draw_g !== null) + this.draw_g.select(".tooltip_bin").remove(); + this.ProvideUserTooltip(null); + return null; + } + + var histo = this.GetObject(), + h = this.tt_handle, i, + ttrect = this.draw_g.select(".tooltip_bin"); + + if (h.candle) { + // process tooltips for candle + + var p; + + for (i=0;i=h.candle.length) { + ttrect.remove(); + this.ProvideUserTooltip(null); + return null; + } + + var res = { x: pnt.x, y: pnt.y, + color1: this.lineatt.color, color2: this.fillatt.color, + lines: this.GetCandleTips(p), exact: true, menu: true }; + + if (ttrect.empty()) + ttrect = this.draw_g.append("svg:rect") + .attr("class","tooltip_bin h1bin") + .style("pointer-events","none"); + + res.changed = ttrect.property("current_bin") !== i; + + if (res.changed) + ttrect.attr("x", p.x1) + .attr("width", p.x2-p.x1) + .attr("y", p.yy1) + .attr("height", p.yy2- p.yy1) + .style("opacity", "0.7") + .property("current_bin", i); + + + if (this.IsUserTooltipCallback() && res.changed) { + this.ProvideUserTooltip({ obj: histo, name: histo.fName, + bin: i+1, cont: p.median, binx: i+1, biny: 1, + grx: pnt.x, gry: pnt.y }); + } + + return res; + + } + + var i, j, find = 0; + + // search bin position + for (i = h.i1; i < h.i2; ++i) + if ((pnt.x>=h.grx[i]) && (pnt.x<=h.grx[i+1])) { ++find; break; } + + for (j = h.j1; j <= h.j2; ++j) + if ((pnt.y>=h.gry[j+1]) && (pnt.y<=h.gry[j])) { ++find; break; } + + var binz = (find === 2) ? histo.getBinContent(i+1,j+1) : 0; + + var colindx = (find === 2) ? this.getValueColor(binz, true) : null; + + if ((find !== 2) || (colindx === null)) { + ttrect.remove(); + this.ProvideUserTooltip(null); + return null; + } + + var res = { x: pnt.x, y: pnt.y, + color1: this.lineatt.color, color2: this.fillatt.color, + lines: this.GetBinTips(i, j), exact: true, menu: true }; + + if (this.options.Color > 0) res.color2 = this.getValueColor(binz); + + if (ttrect.empty()) + ttrect = this.draw_g.append("svg:rect") + .attr("class","tooltip_bin h1bin") + .style("pointer-events","none"); + + res.changed = ttrect.property("current_bin") !== i*10000 + j; + + if (res.changed) + ttrect.attr("x", h.grx[i]) + .attr("width", h.grx[i+1] - h.grx[i]) + .attr("y", h.gry[j+1]) + .attr("height", h.gry[j] - h.gry[j+1]) + .style("opacity", "0.7") + .property("current_bin", i*10000 + j); + + if (this.IsUserTooltipCallback() && res.changed) { + this.ProvideUserTooltip({ obj: histo, name: histo.fName, + bin: histo.getBin(i+1, j+1), cont: binz, binx: i+1, biny: j+1, + grx: pnt.x, gry: pnt.y }); + } + + return res; + } + + JSROOT.TH2Painter.prototype.CanZoomIn = function(axis,min,max) { + // check if it makes sense to zoom inside specified axis range + if ((axis=="x") && (this.GetIndexX(max,0.5) - this.GetIndexX(min,0) > 1)) return true; + + if ((axis=="y") && (this.GetIndexY(max,0.5) - this.GetIndexY(min,0) > 1)) return true; + + if (axis=="z") return true; + + return false; + } + + JSROOT.TH2Painter.prototype.Draw2D = function(call_back, resize) { + + if (typeof this.Create3DScene == 'function') + this.Create3DScene(-1); + + // draw new palette, resize frame if required + var pp = this.DrawColorPalette((this.options.Zscale > 0) && (this.options.Color > 0), true); + + this.DrawAxes(); + + this.DrawGrids(); + + this.DrawBins(); + + // redraw palette once again when contours are available + //if (pp) pp.WhenReady( function() { pp.DrawPave(); }); + if (pp) pp.DrawPave(); + + this.DrawTitle(); + + this.AddInteractive(); + + JSROOT.CallBack(call_back); + } + + JSROOT.TH2Painter.prototype.Draw3D = function(call_back) { + JSROOT.AssertPrerequisites('3d', function() { + this.Create3DScene = JSROOT.Painter.HPainter_Create3DScene; + this.Draw3D = JSROOT.Painter.TH2Painter_Draw3D; + this.Draw3D(call_back); + }.bind(this)); + } + + JSROOT.TH2Painter.prototype.Redraw = function(resize) { + this.CreateXY(); + + var func_name = (this.options.Lego > 0) ? "Draw3D" : "Draw2D"; + + this[func_name](null, resize); + } + + JSROOT.Painter.drawHistogram2D = function(divid, histo, opt) { + // create painter and add it to canvas + JSROOT.extend(this, new JSROOT.TH2Painter(histo)); + + this.SetDivId(divid, 1); + + // here we deciding how histogram will look like and how will be shown + this.options = this.DecodeOptions(opt); + + this._can_move_colz = true; + + this.CheckPadRange(); + + this.ScanContent(); + + // create X/Y only when frame is adjusted, probably should be done differently + this.CreateXY(); + + // check if we need to create statbox + if (JSROOT.gStyle.AutoStat && this.create_canvas) + this.CreateStat(); + + var func_name = (this.options.Lego > 0) ? "Draw3D" : "Draw2D"; + + this[func_name](function() { + this.DrawNextFunction(0, function() { + if (this.options.Lego == 0) { + // this.AddInteractive(); + if (this.options.AutoZoom) this.AutoZoom(); + } + this.FillToolbar(); + this.DrawingReady(); + }.bind(this)); + + }.bind(this)); + + return this; + } + + return JSROOT.Painter; + +})); \ No newline at end of file diff --git a/visualisations/JsRoot460/scripts/JSRootPainter.more.min.js b/visualisations/JsRoot460/scripts/JSRootPainter.more.min.js new file mode 100644 index 0000000..be12a44 --- /dev/null +++ b/visualisations/JsRoot460/scripts/JSRootPainter.more.min.js @@ -0,0 +1 @@ +(function(a){if(typeof define==="function"&&define.amd){define(["d3","JSRootPainter","JSRootMath"],a)}else{if(typeof d3!="object"){throw new Error("This extension requires d3.v3.js","JSRootPainter.more.js")}if(typeof JSROOT=="undefined"){throw new Error("JSROOT is not defined","JSRootPainter.more.js")}if(typeof JSROOT.Painter!="object"){throw new Error("JSROOT.Painter not defined","JSRootPainter.more.js")}a(d3,JSROOT)}}(function(b,a){a.ToolbarIcons.th2color={recs:[{x:0,y:256,w:13,h:39,f:"rgb(38,62,168)"},{x:13,y:371,w:39,h:39},{y:294,h:39},{y:256,h:39},{y:218,h:39},{x:51,y:410,w:39,h:39},{y:371,h:39},{y:333,h:39},{y:294},{y:256,h:39},{y:218,h:39},{y:179,h:39},{y:141,h:39},{y:102,h:39},{y:64},{x:90,y:448,w:39,h:39},{y:410},{y:371,h:39},{y:333,h:39,f:"rgb(22,82,205)"},{y:294},{y:256,h:39,f:"rgb(16,100,220)"},{y:218,h:39},{y:179,h:39,f:"rgb(22,82,205)"},{y:141,h:39},{y:102,h:39,f:"rgb(38,62,168)"},{y:64},{y:0,h:27},{x:128,y:448,w:39,h:39},{y:410},{y:371,h:39},{y:333,h:39,f:"rgb(22,82,205)"},{y:294,f:"rgb(20,129,214)"},{y:256,h:39,f:"rgb(9,157,204)"},{y:218,h:39,f:"rgb(14,143,209)"},{y:179,h:39,f:"rgb(20,129,214)"},{y:141,h:39,f:"rgb(16,100,220)"},{y:102,h:39,f:"rgb(22,82,205)"},{y:64,f:"rgb(38,62,168)"},{y:26,h:39},{y:0,h:27},{x:166,y:486,h:14},{y:448,h:39},{y:410},{y:371,h:39,f:"rgb(22,82,205)"},{y:333,h:39,f:"rgb(20,129,214)"},{y:294,f:"rgb(82,186,146)"},{y:256,h:39,f:"rgb(179,189,101)"},{y:218,h:39,f:"rgb(116,189,129)"},{y:179,h:39,f:"rgb(82,186,146)"},{y:141,h:39,f:"rgb(14,143,209)"},{y:102,h:39,f:"rgb(16,100,220)"},{y:64,f:"rgb(38,62,168)"},{y:26,h:39},{x:205,y:486,w:39,h:14},{y:448,h:39},{y:410},{y:371,h:39,f:"rgb(16,100,220)"},{y:333,h:39,f:"rgb(9,157,204)"},{y:294,f:"rgb(149,190,113)"},{y:256,h:39,f:"rgb(244,198,59)"},{y:218,h:39},{y:179,h:39,f:"rgb(226,192,75)"},{y:141,h:39,f:"rgb(13,167,195)"},{y:102,h:39,f:"rgb(18,114,217)"},{y:64,f:"rgb(22,82,205)"},{y:26,h:39,f:"rgb(38,62,168)"},{x:243,y:448,w:39,h:39},{y:410},{y:371,h:39,f:"rgb(18,114,217)"},{y:333,h:39,f:"rgb(30,175,179)"},{y:294,f:"rgb(209,187,89)"},{y:256,h:39,f:"rgb(251,230,29)"},{y:218,h:39,f:"rgb(249,249,15)"},{y:179,h:39,f:"rgb(226,192,75)"},{y:141,h:39,f:"rgb(30,175,179)"},{y:102,h:39,f:"rgb(18,114,217)"},{y:64,f:"rgb(38,62,168)"},{y:26,h:39},{x:282,y:448,h:39},{y:410},{y:371,h:39,f:"rgb(18,114,217)"},{y:333,h:39,f:"rgb(14,143,209)"},{y:294,f:"rgb(149,190,113)"},{y:256,h:39,f:"rgb(226,192,75)"},{y:218,h:39,f:"rgb(244,198,59)"},{y:179,h:39,f:"rgb(149,190,113)"},{y:141,h:39,f:"rgb(9,157,204)"},{y:102,h:39,f:"rgb(18,114,217)"},{y:64,f:"rgb(38,62,168)"},{y:26,h:39},{x:320,y:448,w:39,h:39},{y:410},{y:371,h:39,f:"rgb(22,82,205)"},{y:333,h:39,f:"rgb(20,129,214)"},{y:294,f:"rgb(46,183,164)"},{y:256,h:39},{y:218,h:39,f:"rgb(82,186,146)"},{y:179,h:39,f:"rgb(9,157,204)"},{y:141,h:39,f:"rgb(20,129,214)"},{y:102,h:39,f:"rgb(16,100,220)"},{y:64,f:"rgb(38,62,168)"},{y:26,h:39},{x:358,y:448,h:39},{y:410},{y:371,h:39,f:"rgb(22,82,205)"},{y:333,h:39},{y:294,f:"rgb(16,100,220)"},{y:256,h:39,f:"rgb(20,129,214)"},{y:218,h:39,f:"rgb(14,143,209)"},{y:179,h:39,f:"rgb(18,114,217)"},{y:141,h:39,f:"rgb(22,82,205)"},{y:102,h:39,f:"rgb(38,62,168)"},{y:64},{y:26,h:39},{x:397,y:448,w:39,h:39},{y:371,h:39},{y:333,h:39},{y:294,f:"rgb(22,82,205)"},{y:256,h:39},{y:218,h:39},{y:179,h:39,f:"rgb(38,62,168)"},{y:141,h:39},{y:102,h:39},{y:64},{y:26,h:39},{x:435,y:410,h:39},{y:371,h:39},{y:333,h:39},{y:294},{y:256,h:39},{y:218,h:39},{y:179,h:39},{y:141,h:39},{y:102,h:39},{y:64},{x:474,y:256,h:39},{y:179,h:39}]};a.ToolbarIcons.th2colorz={recs:[{x:128,y:486,w:256,h:26,f:"rgb(38,62,168)"},{y:461,f:"rgb(22,82,205)"},{y:435,f:"rgb(16,100,220)"},{y:410,f:"rgb(18,114,217)"},{y:384,f:"rgb(20,129,214)"},{y:358,f:"rgb(14,143,209)"},{y:333,f:"rgb(9,157,204)"},{y:307,f:"rgb(13,167,195)"},{y:282,f:"rgb(30,175,179)"},{y:256,f:"rgb(46,183,164)"},{y:230,f:"rgb(82,186,146)"},{y:205,f:"rgb(116,189,129)"},{y:179,f:"rgb(149,190,113)"},{y:154,f:"rgb(179,189,101)"},{y:128,f:"rgb(209,187,89)"},{y:102,f:"rgb(226,192,75)"},{y:77,f:"rgb(244,198,59)"},{y:51,f:"rgb(253,210,43)"},{y:26,f:"rgb(251,230,29)"},{y:0,f:"rgb(249,249,15)"}]};a.ToolbarIcons.th2draw3d={path:"M172.768,0H51.726C23.202,0,0.002,23.194,0.002,51.712v89.918c0,28.512,23.2,51.718,51.724,51.718h121.042 c28.518,0,51.724-23.2,51.724-51.718V51.712C224.486,23.194,201.286,0,172.768,0z M177.512,141.63c0,2.611-2.124,4.745-4.75,4.745 H51.726c-2.626,0-4.751-2.134-4.751-4.745V51.712c0-2.614,2.125-4.739,4.751-4.739h121.042c2.62,0,4.75,2.125,4.75,4.739 L177.512,141.63L177.512,141.63z M460.293,0H339.237c-28.521,0-51.721,23.194-51.721,51.712v89.918c0,28.512,23.2,51.718,51.721,51.718h121.045 c28.521,0,51.721-23.2,51.721-51.718V51.712C512.002,23.194,488.802,0,460.293,0z M465.03,141.63c0,2.611-2.122,4.745-4.748,4.745 H339.237c-2.614,0-4.747-2.128-4.747-4.745V51.712c0-2.614,2.133-4.739,4.747-4.739h121.045c2.626,0,4.748,2.125,4.748,4.739 V141.63z M172.768,256.149H51.726c-28.524,0-51.724,23.205-51.724,51.726v89.915c0,28.504,23.2,51.715,51.724,51.715h121.042 c28.518,0,51.724-23.199,51.724-51.715v-89.915C224.486,279.354,201.286,256.149,172.768,256.149z M177.512,397.784 c0,2.615-2.124,4.736-4.75,4.736H51.726c-2.626-0.006-4.751-2.121-4.751-4.736v-89.909c0-2.626,2.125-4.753,4.751-4.753h121.042 c2.62,0,4.75,2.116,4.75,4.753L177.512,397.784L177.512,397.784z M460.293,256.149H339.237c-28.521,0-51.721,23.199-51.721,51.726v89.915c0,28.504,23.2,51.715,51.721,51.715h121.045 c28.521,0,51.721-23.199,51.721-51.715v-89.915C512.002,279.354,488.802,256.149,460.293,256.149z M465.03,397.784 c0,2.615-2.122,4.736-4.748,4.736H339.237c-2.614,0-4.747-2.121-4.747-4.736v-89.909c0-2.626,2.121-4.753,4.747-4.753h121.045 c2.615,0,4.748,2.116,4.748,4.753V397.784z"};a.Painter.CreateDefaultPalette=function(){function l(w,v,z){var i,x,y;if(z<1e-300){i=x=y=v}else{function u(A,s,r){if(r<0){r+=1}if(r>1){r-=1}if(r<1/6){return A+(s-A)*6*r}if(r<1/2){return s}if(r<2/3){return A+(s-A)*(2/3-r)*6}return A}var o=v<0.5?v*(1+z):v+z-v*z;var t=2*v-o;i=u(t,o,w+1/3);x=u(t,o,w);y=u(t,o,w-1/3)}return"rgb("+Math.round(i*255)+","+Math.round(x*255)+","+Math.round(y*255)+")"}var d=[],g=1,m=0.5,e=280,c=0,k=50;for(var f=0;f0)&&(d<10)){return a.Painter.CreateGrayPalette()}if(d<51){return a.Painter.CreateDefaultPalette()}if(d>112){d=57}var g,f,c,e=[0,0.125,0.25,0.375,0.5,0.625,0.75,0.875,1];switch(d){case 51:g=[0,9,13,17,24,32,27,25,29];f=[0,0,0,2,37,74,113,160,221];c=[28,42,59,78,98,129,154,184,221];break;case 52:g=[0,32,64,96,128,160,192,224,255];f=[0,32,64,96,128,160,192,224,255];c=[0,32,64,96,128,160,192,224,255];break;case 53:g=[0,45,99,156,212,230,237,234,242];f=[0,0,0,45,101,168,238,238,243];c=[0,1,1,3,9,8,11,95,230];break;case 54:g=[0,22,44,68,93,124,160,192,237];f=[0,16,41,67,93,125,162,194,241];c=[97,100,99,99,93,68,44,26,74];break;case 55:g=[0,5,15,35,102,196,208,199,110];f=[0,48,124,192,206,226,97,16,0];c=[99,142,198,201,90,22,13,8,2];break;case 56:g=[242,234,237,230,212,156,99,45,0];f=[243,238,238,168,101,45,0,0,0];c=[230,95,11,8,9,3,1,1,0];break;case 57:g=[0.2082*255,0.0592*255,0.078*255,0.0232*255,0.1802*255,0.5301*255,0.8186*255,0.9956*255,0.9764*255];f=[0.1664*255,0.3599*255,0.5041*255,0.6419*255,0.7178*255,0.7492*255,0.7328*255,0.7862*255,0.9832*255];c=[0.5293*255,0.8684*255,0.8385*255,0.7914*255,0.6425*255,0.4662*255,0.3499*255,0.1968*255,0.0539*255];break;case 58:g=[0,0.0956*255,0.0098*255,0.2124*255,0.6905*255,0.9242*255,0.7914*255,0.7596*255,1*255];f=[0,0.1147*255,0.3616*255,0.5041*255,0.4577*255,0.4691*255,0.6905*255,0.9237*255,1*255];c=[0,0.2669*255,0.3121*255,0.1318*255,0.2236*255,0.6741*255,0.9882*255,0.9593*255,1*255];break;case 59:g=[13,23,25,63,76,104,137,161,206];f=[95,67,37,21,0,12,35,52,79];c=[4,3,2,6,11,22,49,98,208];break;case 60:g=[0,61,89,122,143,160,185,204,231];f=[0,0,0,0,14,37,72,132,235];c=[0,140,224,144,4,5,6,9,13];break;case 61:g=[14,7,2,0,5,11,55,131,229];f=[105,56,26,1,42,74,131,171,229];c=[2,21,35,60,92,113,160,185,229];break;case 62:g=[0,0,0,70,148,231,235,237,244];f=[0,0,0,0,0,69,67,216,244];c=[0,102,228,231,177,124,137,20,244];break;case 63:g=[50,56,63,68,93,121,165,192,241];f=[66,81,91,96,111,128,155,189,241];c=[97,91,75,65,77,103,143,167,217];break;case 64:g=[145,166,167,156,131,114,101,112,132];f=[158,178,179,181,163,154,144,152,159];c=[190,199,201,192,176,169,160,166,190];break;case 65:g=[93,91,99,108,130,125,132,155,174];f=[126,124,128,129,131,121,119,153,173];c=[103,94,87,85,80,85,107,120,146];break;case 66:g=[24,40,69,90,104,114,120,132,103];f=[29,52,94,127,150,162,159,151,101];c=[29,52,96,132,162,181,184,186,131];break;case 67:g=[46,38,61,92,113,121,132,150,191];f=[46,36,40,69,110,135,131,92,34];c=[46,80,74,70,81,105,165,211,225];break;case 68:g=[0,4,12,30,52,101,142,190,237];f=[0,40,86,121,140,172,187,213,240];c=[0,9,14,18,21,23,27,35,101];break;case 69:g=[198,206,206,211,198,181,161,171,244];f=[103,133,150,172,178,174,163,175,244];c=[49,54,55,66,91,130,184,224,244];break;case 70:g=[243,243,240,240,241,239,186,151,129];f=[0,46,99,149,194,220,183,166,147];c=[6,8,36,91,169,235,246,240,233];break;case 71:g=[22,19,19,25,35,53,88,139,210];f=[0,32,69,108,135,159,183,198,215];c=[77,96,110,116,110,100,90,78,70];break;case 72:g=[68,116,165,182,189,180,145,111,71];f=[37,82,135,178,204,225,221,202,147];c=[16,55,105,147,196,226,232,224,178];break;case 73:g=[61,99,136,181,213,225,198,136,24];f=[149,140,96,83,132,178,190,135,22];c=[214,203,168,135,110,100,111,113,22];break;case 74:g=[76,120,156,183,197,180,162,154,140];f=[34,35,42,69,102,137,164,188,197];c=[64,69,78,105,142,177,205,217,198];break;case 75:g=[37,102,157,188,196,214,223,235,251];f=[37,29,25,37,67,91,132,185,251];c=[37,32,33,45,66,98,137,187,251];break;case 76:g=[79,100,119,137,153,172,192,205,250];f=[63,79,93,103,115,135,167,196,250];c=[51,59,66,61,62,70,110,160,250];break;case 77:g=[43,44,50,66,125,172,178,155,157];f=[63,63,85,101,138,163,122,51,39];c=[121,101,58,44,47,55,57,44,43];break;case 78:g=[0,41,62,79,90,87,99,140,228];f=[0,57,81,93,85,70,71,125,228];c=[95,91,91,82,60,43,44,112,228];break;case 79:g=[49,59,72,88,114,141,176,205,222];f=[78,72,66,57,59,75,106,142,173];c=[78,55,46,40,39,39,40,41,47];break;case 80:g=[243,222,201,185,165,158,166,187,219];f=[94,108,132,135,125,96,68,51,61];c=[7,9,12,19,45,89,118,146,118];break;case 81:g=[19,44,74,105,137,166,194,206,220];f=[19,28,40,55,82,110,159,181,220];c=[19,42,68,96,129,157,188,203,220];break;case 82:g=[33,44,70,99,140,165,199,211,216];f=[38,50,76,105,140,165,191,189,167];c=[55,67,97,124,140,166,163,129,52];break;case 83:g=[0,33,73,124,136,152,159,171,223];f=[0,43,92,124,134,126,121,144,223];c=[0,43,68,76,73,64,72,114,223];break;case 84:g=[5,18,45,124,193,223,205,128,49];f=[48,134,207,230,193,113,28,0,7];c=[6,15,41,121,193,226,208,130,49];break;case 85:g=[180,106,104,135,164,188,189,165,144];f=[72,126,154,184,198,207,205,190,179];c=[41,120,158,188,194,181,145,100,62];break;case 86:g=[57,72,94,117,136,154,174,192,215];f=[0,33,68,109,140,171,192,196,209];c=[116,137,173,201,200,201,203,190,187];break;case 87:g=[31,71,123,160,210,222,214,199,183];f=[40,117,171,211,231,220,190,132,65];c=[234,214,228,222,210,160,105,60,34];break;case 88:g=[123,108,109,126,154,172,188,196,218];f=[184,138,130,133,154,175,188,196,218];c=[208,130,109,99,110,122,150,171,218];break;case 89:g=[105,106,122,143,159,172,176,181,207];f=[252,197,194,187,174,162,153,136,125];c=[146,133,144,155,163,167,166,162,174];break;case 90:g=[171,141,145,152,154,159,163,158,177];f=[236,143,100,63,53,55,44,31,6];c=[59,48,46,44,42,54,82,112,179];break;case 91:g=[180,190,209,223,204,228,205,152,91];f=[93,125,147,172,181,224,233,198,158];c=[236,218,160,133,114,132,162,220,218];break;case 92:g=[225,183,162,135,115,111,119,145,211];f=[205,177,166,135,124,117,117,132,172];c=[186,165,155,135,126,130,150,178,226];break;case 93:g=[39,43,59,63,80,116,153,177,223];f=[39,43,59,74,91,114,139,165,223];c=[39,50,59,70,85,115,151,176,223];break;case 94:g=[0,38,60,76,84,89,101,128,204];f=[0,10,15,23,35,57,83,123,199];c=[0,11,22,40,63,86,97,94,85];break;case 95:g=[94,112,141,165,167,140,91,49,27];f=[27,46,88,135,166,161,135,97,58];c=[42,52,81,106,139,158,155,137,116];break;case 96:g=[30,49,79,117,135,151,146,138,147];f=[63,60,72,90,94,94,68,46,16];c=[18,28,41,56,62,63,50,36,21];break;case 97:g=[0,30,63,101,143,152,169,187,230];f=[0,14,28,42,58,61,67,74,91];c=[39,26,21,18,15,14,14,13,13];break;case 98:g=[149,140,164,179,182,181,131,87,61];f=[62,70,107,136,144,138,117,87,74];c=[40,38,45,49,49,49,38,32,34];break;case 99:g=[99,112,148,165,179,182,183,183,208];f=[39,40,57,79,104,127,148,161,198];c=[15,16,18,33,51,79,103,129,177];break;case 100:g=[99,116,154,174,200,196,201,201,230];f=[0,0,8,32,58,83,119,136,173];c=[5,6,7,9,9,14,17,19,24];break;case 101:g=[82,106,126,141,155,163,142,107,66];f=[62,44,69,107,135,152,149,132,119];c=[39,25,31,60,73,68,49,72,188];break;case 102:g=[18,29,44,72,116,158,184,208,221];f=[27,46,71,105,146,177,189,190,183];c=[39,55,80,108,130,133,124,100,76];break;case 103:g=[0,48,119,173,212,224,228,228,245];f=[0,13,30,47,79,127,167,205,245];c=[0,68,75,43,16,22,55,128,245];break;case 104:g=[34,70,129,187,225,226,216,193,179];f=[48,91,147,194,226,229,196,110,12];c=[234,212,216,224,206,110,53,40,29];break;case 105:g=[30,55,103,147,174,203,188,151,105];f=[0,65,138,182,187,175,121,53,9];c=[191,202,212,208,171,140,97,57,30];break;case 106:g=[112,97,113,125,138,159,178,188,225];f=[16,17,24,37,56,81,110,136,189];c=[38,35,46,59,78,103,130,152,201];break;case 107:g=[18,72,5,23,29,201,200,98,29];f=[0,0,43,167,211,117,0,0,0];c=[51,203,177,26,10,9,8,3,0];break;case 108:g=[19,42,64,88,118,147,175,187,205];f=[19,55,89,125,154,169,161,129,70];c=[19,32,47,70,100,128,145,130,75];break;case 109:g=[33,31,42,68,86,111,141,172,227];f=[255,175,145,106,88,55,15,0,0];c=[255,205,202,203,208,205,203,206,231];break;case 110:g=[0,25,50,79,110,145,181,201,254];f=[0,16,30,46,63,82,101,124,179];c=[0,12,21,29,39,49,61,74,103];break;case 111:g=[0,13,30,44,72,120,156,200,247];f=[0,36,84,117,141,153,151,158,247];c=[0,94,100,82,56,66,76,131,247];break;case 112:g=[26,51,43,33,28,35,74,144,246];f=[9,24,55,87,118,150,180,200,222];c=[30,96,112,114,112,101,72,35,0];break;default:return a.Painter.CreateDefaultPalette()}return a.Painter.CreateGradientColorTable(e,g,f,c,255,h)};a.Painter.drawEllipse=function(e,d,c){this.SetDivId(e);this.Redraw=function(){var j=this.GetObject();if(!this.lineatt){this.lineatt=a.Painter.createAttLine(j)}if(!this.fillatt){this.fillatt=this.createAttFill(j)}this.RecreateDrawG(this.main_painter()==null);var r=this.AxisToSvg("x",j.fX1);var p=this.AxisToSvg("y",j.fY1);var i=this.AxisToSvg("x",j.fX1+j.fR1)-r;var g=p-this.AxisToSvg("y",j.fY1+j.fR2);if((j.fPhimin==0)&&(j.fPhimax==360)&&(j.fTheta==0)){this.draw_g.append("svg:ellipse").attr("cx",r.toFixed(1)).attr("cy",p.toFixed(1)).attr("rx",i.toFixed(1)).attr("ry",g.toFixed(1)).call(this.lineatt.func).call(this.fillatt.func);return}var m=Math.cos(Math.PI*j.fTheta/180);var u=Math.sin(Math.PI*j.fTheta/180);var t=i*Math.cos(j.fPhimin*Math.PI/180);var l=g*Math.sin(j.fPhimin*Math.PI/180);var h=t*m-l*u;var q=-t*u-l*m;var s=i*Math.cos(j.fPhimax*Math.PI/180);var k=g*Math.sin(j.fPhimax*Math.PI/180);var f=s*m-k*u;var o=-s*u-k*m;this.draw_g.attr("transform","translate("+r.toFixed(1)+","+p.toFixed(1)+")").append("svg:path").attr("d","M 0,0 L "+h.toFixed(1)+","+q.toFixed(1)+" A "+i.toFixed(1)+" "+g.toFixed(1)+" "+-j.fTheta.toFixed(1)+" 1 0 "+f.toFixed(1)+","+o.toFixed(1)+" L 0,0 Z").call(this.lineatt.func).call(this.fillatt.func)};this.Redraw();return this.DrawingReady()};a.Painter.drawLine=function(e,d,c){this.SetDivId(e);this.Redraw=function(){var g=this.GetObject(),f=a.Painter.createAttLine(g);this.RecreateDrawG(this.main_painter()==null);this.draw_g.append("svg:line").attr("x1",this.AxisToSvg("x",g.fX1).toFixed(1)).attr("y1",this.AxisToSvg("y",g.fY1).toFixed(1)).attr("x2",this.AxisToSvg("x",g.fX2).toFixed(1)).attr("y2",this.AxisToSvg("y",g.fY2).toFixed(1)).call(f.func)};this.Redraw();return this.DrawingReady()};a.Painter.drawBox=function(e,d,c){this.SetDivId(e);this.Redraw=function(){var l=this.GetObject(),f=a.Painter.createAttLine(l),k=this.createAttFill(l);this.RecreateDrawG(this.main_painter()==null);var h=Math.round(this.AxisToSvg("x",l.fX1)),g=Math.round(this.AxisToSvg("x",l.fX2)),j=Math.round(this.AxisToSvg("y",l.fY1)),i=Math.round(this.AxisToSvg("y",l.fY2));this.draw_g.append("svg:rect").attr("x",Math.min(h,g)).attr("y",Math.min(j,i)).attr("width",Math.abs(g-h)).attr("height",Math.abs(j-i)).call(f.func).call(k.func)};this.Redraw();return this.DrawingReady()};a.Painter.drawArrow=function(e,d,c){this.SetDivId(e);this.Redraw=function(){var k=this.GetObject();if(!this.lineatt){this.lineatt=a.Painter.createAttLine(k)}if(!this.fillatt){this.fillatt=this.createAttFill(k)}var f=Math.max(this.pad_width(),this.pad_height())*k.fArrowSize;if(f<3){f=3}var w=f*Math.tan(k.fAngle/2*(Math.PI/180));this.RecreateDrawG(this.main_painter()==null);var z=this.AxisToSvg("x",k.fX1),l=this.AxisToSvg("y",k.fY1),y=this.AxisToSvg("x",k.fX2),i=this.AxisToSvg("y",k.fY2),g="M0,0 L"+f.toFixed(1)+","+w.toFixed(1)+" L0,"+(w*2).toFixed(1),s="M"+f.toFixed(1)+", 0 L 0,"+w.toFixed(1)+" L "+f.toFixed(1)+","+(w*2).toFixed(1),o=null,p=null,u=null,h=null,t=k.fOption,x=t.length;if(t.indexOf("<")==0){var j=(t.indexOf("<|")==0);if(!h){h=this.draw_g.append("defs")}o="jsroot_arrowmarker_"+a.Painter.arrowcnt++;var r=h.append("svg:marker").attr("id",o).attr("markerWidth",f.toFixed(1)).attr("markerHeight",(w*2).toFixed(1)).attr("refX","0").attr("refY",w.toFixed(1)).attr("orient","auto").attr("markerUnits","userSpaceOnUse").append("svg:path").style("fill","none").attr("d",s+(j?" Z":"")).call(this.lineatt.func);if(j){r.call(this.fillatt.func)}}var q=0;if(t.indexOf("->-")>=0){q=1}else{if(t.indexOf("-|>-")>=0){q=11}else{if(t.indexOf("-<-")>=0){q=2}else{if(t.indexOf("-<|-")>=0){q=12}}}}if(q>0){var j=q>10;if(!h){h=this.draw_g.append("defs")}p="jsroot_arrowmarker_"+a.Painter.arrowcnt++;var A=h.append("svg:marker").attr("id",p).attr("markerWidth",f.toFixed(1)).attr("markerHeight",(w*2).toFixed(1)).attr("refX",(f*0.5).toFixed(1)).attr("refY",w.toFixed(1)).attr("orient","auto").attr("markerUnits","userSpaceOnUse").append("svg:path").style("fill","none").attr("d",((q%10==1)?g:s)+((q>10)?" Z":"")).call(this.lineatt.func);if(q>10){A.call(this.fillatt.func)}}if(t.lastIndexOf(">")==x-1){var j=(t.lastIndexOf("|>")==x-2)&&(x>1);if(!h){h=this.draw_g.append("defs")}u="jsroot_arrowmarker_"+a.Painter.arrowcnt++;var m=h.append("svg:marker").attr("id",u).attr("markerWidth",f.toFixed(1)).attr("markerHeight",(w*2).toFixed(1)).attr("refX",f.toFixed(1)).attr("refY",w.toFixed(1)).attr("orient","auto").attr("markerUnits","userSpaceOnUse").append("svg:path").style("fill","none").attr("d",g+(j?" Z":"")).call(this.lineatt.func);if(j){m.call(this.fillatt.func)}}var v=this.draw_g.append("svg:path").attr("d","M"+z.toFixed(1)+","+l.toFixed(1)+((p==null)?"":"L"+(z/2+y/2).toFixed(1)+","+(l/2+i/2).toFixed(1))+" L"+y.toFixed(1)+","+i.toFixed(1)).call(this.lineatt.func);if(o!=null){v.style("marker-start","url(#"+o+")")}if(p!=null){v.style("marker-mid","url(#"+p+")")}if(u!=null){v.style("marker-end","url(#"+u+")")}};if(!("arrowcnt" in a.Painter)){a.Painter.arrowcnt=0}this.Redraw();return this.DrawingReady()};a.Painter.BuildSvgPath=function(h,s,o,d){var f=h.indexOf("bezier")>=0;if(d===undefined){d=f?2:0}if(o===undefined){o=0}function e(u,t){return(t.gry-u.gry)/(t.grx-u.grx)}function k(w){var v=0,u=w.length-1,t=[],z=w[0],y=w[1],x=t[0]=e(z,y);while(++v9){y=A*3/Math.sqrt(y);t[x]=y*v;t[x+1]=y*u}}}x=-1;while(++x<=w){y=(z[Math.min(w,x+1)].grx-z[Math.max(0,x-1)].grx)/(6*(1+t[x]*t[x]));z[x].dgrx=y||0;z[x].dgry=t[x]*y||0}}var j={},r=s[0],g,i=Math.max(r.gry,o+5),m=Math.round(r.grx),l=Math.round(r.gry),q,p;j.path=((h.charAt(0)=="L")?"L":"M")+r.grx.toFixed(d)+","+r.gry.toFixed(d);if(f||h.indexOf("calc")>=0){c(s)}if(f){j.path+="c"+r.dgrx.toFixed(d)+","+r.dgry.toFixed(d)+","}for(n=1;n1){j.path+="s"}j.path+=(r.grx-r.dgrx-g.grx).toFixed(d)+","+(r.gry-r.dgry-g.gry).toFixed(d)+","+(r.grx-g.grx).toFixed(d)+","+(r.gry-g.gry).toFixed(d);i=Math.max(i,g.gry)}else{q=Math.round(r.grx-m);p=Math.round(r.gry-l);j.path+="l"+q+","+p;m+=q;l+=p;i=Math.max(i,l)}}if(o>0){j.close="L"+r.grx.toFixed(d)+","+i.toFixed(d)+"L"+s[0].grx.toFixed(d)+","+i.toFixed(d)+"Z"}return j};a.Painter.drawFunction=function(f,e,d){this.bins=null;this.Eval=function(g){return this.GetObject().evalPar(g)};this.CreateBins=function(u){var l=this.main_painter(),i=0,o=0,p=this.GetObject();if((l!==null)&&!u){if(l.zoom_xmin!==l.zoom_xmax){i=l.zoom_xmin;o=l.zoom_xmax}else{i=l.xmin;o=l.xmax}}if(p.fSave.length>0){var s=p.fSave.length-2,h=p.fSave[s],m=p.fSave[s+1],v=(m-h)/(s-1),r=[];for(var j=0;jo))){continue}r.push({x:g,y:p.fSave[j]})}return r}var h=p.fXmin,m=p.fXmax,t=false,k=this.root_pad();if(i!==o){if(i>h){h=i}if(o0)&&(m>0)){t=true;h=Math.log(h);m=Math.log(m)}var s=Math.max(p.fNpx,101);var v=(m-h)/(s-1);var r=[];for(var j=0;j0){g*=1.05}if(j<0){j*=1.05}}var h=a.Create("TH1I"),m=this.GetObject();h.fName=m.fName+"_hist";h.fTitle=m.fTitle;h.fXaxis.fXmin=l;h.fXaxis.fXmax=i;h.fYaxis.fXmin=j;h.fYaxis.fXmax=g;return h};this.ProcessTooltipFunc=function(g){var i=false;if((g===null)||(this.bins===null)){i=true}else{if((this.bins.length==0)||(g.xthis.bins[this.bins.length-1].grx)){i=true}}if(i){if(this.draw_g!==null){this.draw_g.select(".tooltip_bin").remove()}return null}var m=100000,l=-1,s;for(var k=0;k0){q.lines.push(h)}var p=this.main_painter();if(p!==null){q.lines.push("x = "+p.AxisAsText("x",s.x)+" y = "+p.AxisAsText("y",s.y))}return q};this.Redraw=function(){var p=this.frame_width(),k=this.frame_height(),l=this.GetObject();this.RecreateDrawG(false,"main_layer");this.bins=this.CreateBins(false);var i=this;var m=this.main_painter();var g=this.GetTipName("\n");if(!this.lineatt){this.lineatt=a.Painter.createAttLine(l)}this.lineatt.used=false;if(!this.fillatt){this.fillatt=this.createAttFill(l,undefined,undefined,1)}this.fillatt.used=false;var j,r;for(j=0;j2){var o=k;if((m.hmin!==undefined)&&(m.hmin>=0)){o=Math.round(m.gry(0));if((o>k)||(o<0)){o=k}}var q=a.Painter.BuildSvgPath("bezier",this.bins,o,2);if(this.lineatt.color!="none"){this.draw_g.append("svg:path").attr("class","line").attr("d",q.path).style("fill","none").call(this.lineatt.func)}if(this.fillatt.color!="none"){this.draw_g.append("svg:path").attr("class","area").attr("d",q.path+q.close).style("stroke","none").call(this.fillatt.func)}}delete this.ProcessTooltip;if(a.gStyle.Tooltip>0){this.ProcessTooltip=this.ProcessTooltipFunc}};this.CanZoomIn=function(j,i,g){if(j!=="x"){return false}var m=this.GetObject();if(m.fSave.length>0){var l=m.fNpx;var k=m.fSave[l+1];var h=m.fSave[l+2];return Math.abs(k-h)/lk.max))){k.max=g+i}}}return k};this["GetMinMax"]=function(j){var h={min:0,max:0},k=(j.indexOf("e")>=0),f=this.GetObject();if(this.nostack){for(var g=0;gh.max){h.max=l.max}}}if(f.fMaximum!=-1111){h.max=f.fMaximum}else{h.max*=1.05}if(f.fMinimum!=-1111){h.min=f.fMinimum}}else{h.min=this.GetHistMinMax(f.fStack.arr[0],k).min;h.max=this.GetHistMinMax(f.fStack.arr[f.fStack.arr.length-1],k).max*1.05}var m=this.root_pad();if(m&&m.fLogy){if(h.min<0){h.min=h.max*0.0001}}return h};this["DrawNextHisto"]=function(j,i){var l=null,h=this.GetObject(),g=h.fHists.arr.length;if(j>=g){return this.DrawingReady()}if(j<0){l=h.fHistogram}else{if(this.nostack){l=h.fHists.arr[j]}else{l=h.fStack.arr[g-j-1]}}var f=l.fOption;if((i!="")&&(f.indexOf(i)==-1)){f+=i}if(j>=0){f+="same"}var k=a.draw(this.divid,l,f);if(j<0){this.firstpainter=k}else{this.painters.push(k)}k.WhenReady(this.DrawNextHisto.bind(this,j+1,i))};this["drawStack"]=function(g){var k=this.root_pad(),t=this.GetObject(),p=t.fHists,v=p.arr.length;if(g==null){g=""}else{g=g.toLowerCase()}var o=false;if(g.indexOf("same")!=-1){o=true;g.replace("same","")}this.nostack=g.indexOf("nostack")<0?false:true;if(!this.nostack){this.nostack=!this.BuildStack()}var l=this.GetMinMax(g);if(t.fHistogram===null){var f=0,r=0,u=0,j=0;for(var q=0;qr){r=s.fXaxis.fXmax}if(q==0||s.fYaxis.fXminj){j=s.fYaxis.fXmax}}var s=t.fHists.arr[0];t.fHistogram=a.Create("TH1I");t.fHistogram.fName="unnamed";t.fHistogram.fXaxis=a.clone(s.fXaxis);t.fHistogram.fYaxis=a.clone(s.fYaxis);t.fHistogram.fXaxis.fXmin=f;t.fHistogram.fXaxis.fXmax=r;t.fHistogram.fYaxis.fXmin=u;t.fHistogram.fYaxis.fXmax=j}t.fHistogram.fTitle=t.fTitle;var m=t.fHistogram;if(!m.TestBit(a.TH1StatusBits.kIsZoomed)){if(k&&k.fLogy){m.fMaximum=l.max*(1+0.2*a.log10(l.max/l.min))}else{m.fMaximum=l.max}if(k&&k.fLogy){m.fMinimum=l.min/(1+0.5*a.log10(l.max/l.min))}else{m.fMinimum=l.min}}this.DrawNextHisto(!o?-1:0,g);return this};this["UpdateObject"]=function(k){if(!this.MatchObjectType(k)){return false}var h=false;if(this.firstpainter){if(this.firstpainter.UpdateObject(k.fHistogram)){h=true}}var f=k.fHists.arr.length;for(var g=0;g3)){g--}if(c._typename=="TGraphErrors"){e=1}else{if(c._typename=="TGraphAsymmErrors"||c._typename=="TGraphBentErrors"||c._typename.match(/^RooHist/)){e=2}}this.bins=[];for(f=0;f0){this.xmin=Math.min(this.xmin,d.x-d.exlow,d.x+d.exhigh);this.xmax=Math.max(this.xmax,d.x-d.exlow,d.x+d.exhigh);this.ymin=Math.min(this.ymin,d.y-d.eylow,d.y+d.eyhigh);this.ymax=Math.max(this.ymax,d.y-d.eylow,d.y+d.eyhigh)}else{this.xmin=Math.min(this.xmin,d.x);this.xmax=Math.max(this.xmax,d.x);this.ymin=Math.min(this.ymin,d.y);this.ymax=Math.max(this.ymax,d.y)}}};a.TGraphPainter.prototype.CreateHistogram=function(){var c=this.xmin,h=this.xmax,j=this.ymin,d=this.ymax;if(c>=h){h=c+1}if(j>=d){d=j+1}var o=(h-c)*0.1,m=(d-j)*0.1,l=c-o,e=h+o,i=j-m,f=d+m;if((l<0)&&(c>=0)){l=c*0.9}if((e>0)&&(h<=0)){e=0}var k=this.GetObject();if(k.fMinimum!=-1111){i=j=k.fMinimum}if(k.fMaximum!=-1111){f=d=k.fMaximum}if((i<0)&&(j>=0)){i=0.9*j}var g=a.CreateTH1(100);g.fName=k.fName+"_h";g.fTitle=k.fTitle;g.fXaxis.fXmin=l;g.fXaxis.fXmax=e;g.fYaxis.fXmin=i;g.fYaxis.fXmax=f;g.fMinimum=i;g.fMaximum=f;g.fBits=g.fBits|a.TH1StatusBits.kNoStats;return g};a.TGraphPainter.prototype.OptimizeBins=function(c){if((this.bins.length<30)&&!c){return this.bins}var g=null;if(typeof c=="function"){for(var f=0;f0))&&(e.y_kind=="normal")&&("eylow" in h)&&((h.eylow!=0)||(h.eyhigh!=0))){c.push("error y = -"+e.AxisAsText("y",h.eylow)+"/+"+e.AxisAsText("y",h.eyhigh))}if(g){return c}var f="";for(var i=0;i0?"\n":"")+c[i])}return f};a.TGraphPainter.prototype.DrawBins=function(){this.RecreateDrawG(false,"main_layer");var o=this,t=this.main_painter(),u=this.frame_width(),G=this.frame_height(),k=this.GetObject(),D=0;if(!this.lineatt){this.lineatt=a.Painter.createAttLine(k,undefined,true)}if(!this.fillatt){this.fillatt=this.createAttFill(k,undefined,undefined,1)}this.fillatt.used=false;if(this.fillatt){this.fillatt.used=false}this.draw_kind="none";this.marker_size=0;if(this.lineatt.excl_side!=0){D=this.lineatt.excl_side*this.lineatt.excl_width;if(this.lineatt.width>0){this.optionLine=1}}var v=null;if(this.optionEF>0){v=this.OptimizeBins();for(var B=0;B1?"bezier":"line",v),d=[];for(var B=v.length-1;B>=0;--B){var x=v[B];x.gry=t.gry(x.y+x.eyhigh);d.push(x)}var e=a.Painter.BuildSvgPath(this.optionEF>1?"Lbezier":"Lline",d);this.draw_g.append("svg:path").attr("d",g.path+e.path+"Z").style("stroke","none").call(this.fillatt.func);this.draw_kind="lines"}if(this.optionLine==1||this.optionFill==1||(D!==0)){var c="";if(k._typename=="TCutG"){this.optionFill=1}if(this.optionFill==1){c="Z";D=0}if(v===null){v=this.OptimizeBins()}for(var B=0;B=0;--B){var x=v[B];var C=Math.sqrt(x.dgrx*x.dgrx+x.dgry*x.dgry);x.grx+=D*x.dgry/C;x.gry-=D*x.dgrx/C;f.push(x)}var e=a.Painter.BuildSvgPath("L"+((this.optionCurve===1)?"bezier":"line"),f);this.draw_g.append("svg:path").attr("d",y.path+e.path+"Z").style("stroke","none").call(this.fillatt.func).style("opacity",0.75)}if(this.optionLine||this.optionFill){var H=this.draw_g.append("svg:path").attr("d",y.path+c);if(this.optionLine){H.call(this.lineatt.func)}else{H.style("stroke","none")}if(this.optionFill>0){H.call(this.fillatt.func)}else{H.style("fill","none")}}this.draw_kind="lines"}var A=null;if(this.draw_errors||this.optionRect||this.optionBrackets||this.optionBar){v=this.OptimizeBins(function(K,J){var w=t.grx(K.x);if(!o.optionBar&&((w<0)||(w>u))){return true}var h=t.gry(K.y);if(!o.optionBar&&!o.out_of_range&&((h<0)||(h>G))){return true}K.grx1=Math.round(w);K.gry1=Math.round(h);if(o.has_errors){K.grx0=Math.round(t.grx(K.x-K.exlow)-w);K.grx2=Math.round(t.grx(K.x+K.exhigh)-w);K.gry0=Math.round(t.gry(K.y-K.eylow)-h);K.gry2=Math.round(t.gry(K.y+K.eyhigh)-h);if(o.is_bent){K.grdx0=Math.round(t.gry(K.y+k.fEXlowd[J])-h);K.grdx2=Math.round(t.gry(K.y+k.fEXhighd[J])-h);K.grdy0=Math.round(t.grx(K.x+k.fEYlowd[J])-w);K.grdy2=Math.round(t.grx(K.x+k.fEYhighd[J])-w)}else{K.grdx0=K.grdx2=K.grdy0=K.grdy2=0}}return false});this.draw_kind="nodes";A=this.draw_g.selectAll(".grpoint").data(v).enter().append("svg:g").attr("class","grpoint").attr("transform",function(h){return"translate("+h.grx1+","+h.gry1+")"})}if(this.optionBar){for(var E=1;Ej)?j-h.gry1:0}).attr("width",function(h){return Math.round(h.width)}).attr("height",function(h){if(o.optionBar!==1){return G>h.gry1?G-h.gry1:0}return Math.abs(j-h.gry1)}).call(this.fillatt.func)}if(this.optionRect){A.filter(function(h){return(h.exlow>0)&&(h.exhigh>0)&&(h.eylow>0)&&(h.eyhigh>0)}).append("svg:rect").attr("x",function(h){h.rect=true;return h.grx0}).attr("y",function(h){return h.gry2}).attr("width",function(h){return h.grx2-h.grx0}).attr("height",function(h){return h.gry0-h.gry2}).call(this.fillatt.func)}if(this.optionBrackets){A.filter(function(h){return(h.eylow>0)||(h.eyhigh>0)}).append("svg:path").call(this.lineatt.func).style("fill","none").attr("d",function(h){h.bracket=true;return((h.eylow>0)?"M-5,"+(h.gry0-3)+"v3h10v-3":"")+((h.eyhigh>0)?"M-5,"+(h.gry2+3)+"v-3h10v3":"")})}if(this.draw_errors){var q=this.lineatt.width+a.gStyle.EndErrorSize,z="m0,"+q+"v-"+2*q,l="m"+q+",0h-"+2*q;q=Math.floor((this.lineatt.width-1)/2);A.filter(function(h){return(h.exlow>0)||(h.exhigh>0)||(h.eylow>0)||(h.eyhigh>0)}).append("svg:path").call(this.lineatt.func).style("fill","none").attr("d",function(h){h.error=true;return((h.exlow>0)?"M0,0L"+(h.grx0+q)+","+h.grdx0+z:"")+((h.exhigh>0)?"M0,0L"+(h.grx2-q)+","+h.grdx2+z:"")+((h.eylow>0)?"M0,0L"+h.grdy0+","+(h.gry0-q)+l:"")+((h.eyhigh>0)?"M0,0L"+h.grdy2+","+(h.gry2+q)+l:"")})}if(this.optionMark>0){var r=Math.max(1,Math.round(this.bins.length/50000)),y="",B,I,p,m,F;if(this.optionMark==2){F=3}else{if(this.optionMark==3){F=1}}if(!this.markeratt){this.markeratt=a.Painter.createAttMarker(k,F)}else{this.markeratt.Change(undefined,F)}this.marker_size=this.markeratt.size;this.markeratt.reset_pos();for(B=0;B-this.marker_size)&&(p-this.marker_size)&&(m0){this.draw_g.append("svg:path").attr("d",y).call(this.markeratt.func);if((A===null)&&(this.draw_kind=="none")){this.draw_kind=(this.optionMark==3)?"path":"mark"}}}};a.TGraphPainter.prototype.ProcessTooltip=function(c){if(c===null){if(this.draw_g!==null){this.draw_g.select(".tooltip_bin").remove()}return null}if((this.draw_kind=="lines")||(this.draw_kind=="path")||(this.draw_kind=="mark")){return this.ProcessTooltipForPath(c)}if(this.draw_kind!="nodes"){return null}var e=this.frame_width(),o=this.frame_height(),h=this.main_painter(),l=this,m=null,k=10000000000,g=null;this.draw_g.selectAll(".grpoint").each(function(){var u=b.select(this).datum();if(u===undefined){return}var t=Math.pow(c.x-u.grx1,2);if(c.nproc===1){t+=Math.pow(c.y-u.gry1,2)}if(t>=k){return}var s=null;if(u.error||u.rect||u.marker||u.bracket){s={x1:Math.min(-3,u.grx0),x2:Math.max(3,u.grx2),y1:Math.min(-3,u.gry2),y2:Math.max(3,u.gry0)};if(u.bracket){s.x1=-5;s.x2=5}}else{if(u.bar){s={x1:-u.width/2,x2:u.width/2,y1:0,y2:o-u.gry1};if(l.optionBar===1){var r=h.gry(0);s.y1=(u.gry1>r)?r-u.gry1:0;s.y2=(u.gry1>r)?0:r-u.gry1}}else{s={x1:-5,x2:5,y1:-5,y2:5}}}var q=(c.x>=u.grx1+s.x1)&&(c.x<=u.grx1+s.x2);var p=(c.y>=u.gry1+s.y1)&&(c.y<=u.gry1+s.y2);if(q&&(p||(c.nproc>1))){k=t;m=this;g=s;g.exact=q&&p}});var f=this.draw_g.select(".tooltip_bin");if(m==null){f.remove();return null}var j=b.select(m).datum();var i={x:j.grx1,y:j.gry1,color1:this.lineatt.color,lines:this.TooltipText(j,true)};if(this.fillatt&&this.fillatt.used){i.color2=this.fillatt.color}if(g.exact){i.exact=true}i.menu=i.exact;i.menu_dist=3;if(f.empty()){f=this.draw_g.append("svg:rect").attr("class","tooltip_bin h1bin").style("pointer-events","none")}i.changed=f.property("current_bin")!==m;if(i.changed){f.attr("x",j.grx1+g.x1).attr("width",g.x2-g.x1).attr("y",j.gry1+g.y1).attr("height",g.y2-g.y1).style("opacity","0.3").property("current_bin",m)}return i};a.TGraphPainter.prototype.ProcessTooltipForPath=function(c){if(this.bins===null){return null}var d=(this.draw_kind=="lines"),j=(this.draw_kind=="mark"),r=null,t=10000000000,k=this.main_painter(),q,h,g,e,s;for(e=0;e10)&&d){r=null}var i=Math.max(this.lineatt.width+3,4);if(this.marker_size>0){i=Math.max(Math.round(this.marker_size*7),i)}if(r!==null){t=Math.sqrt(Math.pow(c.x-k.grx(r.x),2)+Math.pow(c.y-k.gry(r.y),2))}if(!d&&!j&&(t>i)){r=null}if(j&&(r!==null)){if((c.nproc==1)&&(t>i)){r=null}else{if((this.bins.length==1)&&(t>3*i)){r=null}}}var o=this.draw_g.select(".tooltip_bin");if(r===null){o.remove();return null}var m={x:k.grx(r.x),y:k.gry(r.y),color1:this.lineatt.color,lines:this.TooltipText(r,true)};if(this.fillatt&&this.fillatt.used){m.color2=this.fillatt.color}if(!d){m.color1=a.Painter.root_colors[this.GetObject().fMarkerColor];if(!m.color2){m.color2=m.color1}}if(o.empty()){o=this.draw_g.append("svg:g").attr("class","tooltip_bin")}var p,l;if((this.optionEF>0)&&d){p=k.gry(r.y-r.eylow);l=k.gry(r.y+r.eyhigh)}else{p=l=k.gry(r.y)}m.exact=(Math.abs(c.x-m.x)<=i)&&((Math.abs(c.y-p)<=i)||(Math.abs(c.y-l)<=i));m.menu=m.exact;m.menu_dist=Math.sqrt((c.x-m.x)*(c.x-m.x)+Math.pow(Math.min(Math.abs(c.y-p),Math.abs(c.y-l)),2));m.changed=o.property("current_bin")!==r;if(m.changed){o.selectAll("*").remove();o.property("current_bin",r);if(j){o.append("svg:rect").attr("class","h1bin").style("pointer-events","none").style("opacity","0.3").attr("x",(m.x-i).toFixed(1)).attr("y",(m.y-i).toFixed(1)).attr("width",(2*i).toFixed(1)).attr("height",(2*i).toFixed(1))}else{o.append("svg:circle").attr("cy",p.toFixed(1));if(Math.abs(p-l)>1){o.append("svg:circle").attr("cy",l.toFixed(1))}var f=o.selectAll("circle").attr("r",i).attr("cx",m.x.toFixed(1));if(!d){f.style("stroke",m.color1=="black"?"green":"black").style("fill","none")}else{if(this.optionLine){f.call(this.lineatt.func)}else{f.style("stroke","black")}if(this.optionFill>0){f.call(this.fillatt.func)}else{f.style("fill","none")}}}}return m};a.TGraphPainter.prototype.UpdateObject=function(d){if(!this.MatchObjectType(d)){return false}if(this.ownhisto){this.main_painter().UpdateObject(d.fHistogram)}var c=this.GetObject();c.fX=d.fX;c.fY=d.fY;c.fNpoints=d.fNpoints;this.CreateBins();return true};a.TGraphPainter.prototype.CanZoomIn=function(f,e,c){var d=this.GetObject();if((d===null)||(f!=="x")){return false}for(var g=0;g=g.fFunctions.arr.length)){return a.CallBack(h)}var e=g.fFunctions.arr[f];var d=g.fFunctions.opt[f];var c=a.draw(this.divid,e,d);if(c){return c.WhenReady(this.DrawNextFunction.bind(this,f+1,h))}this.DrawNextFunction(f+1,h)};a.Painter.drawGraph=function(e,d,c){a.extend(this,new a.TGraphPainter(d));this.CreateBins();this.SetDivId(e,-1);if(this.main_painter()==null){if(d.fHistogram==null){d.fHistogram=this.CreateHistogram()}a.Painter.drawHistogram1D(e,d.fHistogram,"AXIS");this.ownhisto=true}this.SetDivId(e);this.DecodeOptions(c);this.DrawBins();this.DrawNextFunction(0,this.DrawingReady.bind(this));return this};a.Painter.drawMultiGraph=function(e,d,c){this.firstpainter=null;this.autorange=false;this.painters=[];this.SetDivId(e,-1);this.UpdateObject=function(k){if(!this.MatchObjectType(k)){return false}var l=this.GetObject(),g=k.fGraphs;l.fTitle=k.fTitle;var j=false;if(this.firstpainter){var f=k.fHistogram;if(this.autorange&&(f==null)){f=this.ScanGraphsRange(g)}if(this.firstpainter.UpdateObject(f)){j=true}}for(var h=0;h=0){p=0}if(k>0&&f.ymax<=0){k=0}}if(s<0&&f.xmin>=0){if(r){s=0.9*f.xmin}else{s=0}}if(g>0&&f.xmax<=0){if(r){g=1.1*f.xmax}else{g=0}}if(j.fMinimum!=-1111){f.ymin=p=j.fMinimum}if(j.fMaximum!=-1111){f.ymax=k=j.fMaximum}if(p<0&&f.ymin>=0){if(q){p=0.9*f.ymin}}if(k>0&&f.ymax<=0){if(q){k=1.1*f.ymax}}if(p<=0&&q){p=0.001*k}if(s<=0&&r){if(g>1000){s=1}else{s=0.001*g}}if(!l){l=a.Create("TH1I");l.fTitle=j.fTitle;l.fXaxis.fXmin=s;l.fXaxis.fXmax=g}l.fYaxis.fXmin=p;l.fYaxis.fXmax=k;return l};this.DrawAxis=function(){var g=this.GetObject();var f=this.ScanGraphsRange(g.fGraphs,g.fHistogram,this.root_pad());this.firstpainter=a.Painter.drawHistogram1D(this.divid,f,"AXIS")};this.DrawNextFunction=function(i,k){var j=this.GetObject();if((j.fFunctions==null)||(i>=j.fFunctions.arr.length)){return a.CallBack(k)}var h=j.fFunctions.arr[i];var g=j.fFunctions.opt[i];var f=a.draw(this.divid,h,g);if(f){return f.WhenReady(this.DrawNextFunction.bind(this,i+1,k))}this.DrawNextFunction(i+1,k)};this.DrawNextGraph=function(i,h){var f=this.GetObject().fGraphs;if(i>=f.arr.length){return this.DrawNextFunction(0,this.DrawingReady.bind(this))}var g=f.opt[i];if((g==null)||(g=="")){g=h}var j=a.draw(this.divid,f.arr[i],g);this.painters.push(j);j.WhenReady(this.DrawNextGraph.bind(this,i+1,h))};if(c==null){c=""}c=c.toUpperCase().replace("3D","").replace("FB","");if((c.indexOf("A")>=0)||(this.main_painter()==null)){c=c.replace("A","");this.DrawAxis()}this.SetDivId(e);this.DrawNextGraph(0,c);return this};a.Painter.drawLegend=function(e,d,c){a.extend(this,new a.TPavePainter(d));this.SetDivId(e);this.DrawLegendItems=function(u,E){var j=this.GetObject(),y=j.fPrimitives.arr.length,q=j.fNColumns,o=y;if(q<2){q=1}else{while((o-1)*q>=y){o--}}this.StartTextDrawing(j.fTextFont,E/(y*1.2));var N=a.Painter.root_colors[j.fTextColor],r=Math.round(u/q),x=Math.round(0.03*u/q),v=Math.round(0.03*E),t=(E-2*v)/o,k=false;for(var D=0;D0){k=true}else{if(!k){g=F+x}}this.DrawText("start",g,f,F+r-g-x,t,I.fLabel,N)}this.FinishTextDrawing()};this.PaveDrawFunc=this.DrawLegendItems;this.Redraw();return this.DrawingReady()};a.Painter.drawPaletteAxis=function(e,c,d){c.fBorderSize=1;c.fShadowColor=0;a.extend(this,new a.TPavePainter(c));this.SetDivId(e);this.z_handle=new a.TAxisPainter(c.fAxis,true);this.z_handle.SetDivId(e,-1);this.DrawAxisPalette=function(u,N,q){var o=this,M=this.GetObject(),l=M.fAxis,y=(typeof q=="string")&&(q.indexOf("canmove")>0),B=(typeof q=="string")&&(q.indexOf("postpone")>0);var v=l.fNdiv%100;if(v<=0){v=8}var h=parseInt(this.draw_g.attr("x")),g=parseInt(this.draw_g.attr("y")),F=this.pad_width(),E=this.pad_height(),m=l.fLabelOffset*F,t=this.main_painter(),O=0,Q=100,G=t.fContour;l.fTickSize=0.6*u/F;if(G){O=G[0];Q=G[G.length-1]}else{if((t.gmaxbin!==undefined)&&(t.gminbin!==undefined)){O=t.gminbin;Q=t.gmaxbin}else{if((t.hmin!==undefined)&&(t.hmax!==undefined)){O=t.hmin;Q=t.hmax}}}var w=null,R="normal";if(this.root_pad().fLogz){w=b.scale.log();R="log"}else{w=b.scale.linear()}w.domain([O,Q]).range([N,0]);if(!G||B){this.draw_g.append("svg:rect").attr("x",0).attr("y",0).attr("width",u).attr("height",N).attr("fill","white")}else{for(var K=0;K0){D.on("mouseover",function(){b.select(this).transition().duration(100).style("fill",b.select(this).property("fill1"))}).on("mouseout",function(){b.select(this).transition().duration(100).style("fill",b.select(this).property("fill0"))}).append("svg:title").text(G[K].toFixed(2)+" - "+G[K+1].toFixed(2))}if(a.gStyle.Zooming){D.on("dblclick",function(){o.main_painter().Unzoom("z")})}}}this.z_handle.SetAxisConfig("zaxis",R,w,O,Q,O,Q);this.z_handle.DrawAxis(true,this.draw_g,u,N,"translate("+u+", 0)");if(y&&("getBoundingClientRect" in this.draw_g.node())){var k=this.draw_g.node().getBoundingClientRect();var L=(h+parseInt(k.width))-Math.round(0.995*F)+3;if(L>0){this.draw_g.attr("x",h-L).attr("y",g).attr("transform","translate("+(h-L)+", "+g+")");M.fX1NDC-=L/F;M.fX2NDC-=L/F}}if(!a.gStyle.Zooming){return}var s=null,P=false,I=0,H=0,f=null;function x(){if(!P){return}b.event.preventDefault();var i=b.mouse(s);if(i[1]0)?0.3*f:0.0001*this.zmax}if(this.zmin>=this.zmax){this.zmin=0.0001*this.zmax}var e=Math.log(this.zmin)/Math.log(10);var h=Math.log(this.zmax)/Math.log(10);var c=(h-e)/i;this.fContour.push(this.zmin);for(var j=1;j1)&&f.TestBit(a.TH1StatusBits.kUserContour)){this.fContour=a.clone(f.fContour);this.fCustomContour=true}else{var g=20,h=this.minbin,k=this.maxbin;if(f.fContour!=null){g=f.fContour.length}if((this.histo.fMinimum!=-1111)&&(this.histo.fMaximum!=-1111)){h=this.histo.fMinimum;k=this.histo.fMaximum}if(this.zoom_zmin!=this.zoom_zmax){h=this.zoom_zmin;k=this.zoom_zmax}this.CreateContour(g,h,k,this.minposbin)}}if(this.fCustomContour){var i=this.fContour,e=0,c=this.fContour.length-1,j;if(d=i[c]){return c}while(ed){c=j}else{e=j}}return e}if(d0)||(this.options.Color===111))?0:-1}return Math.floor(0.01+(d-this.zmin)*(this.fContour.length-1)/(this.zmax-this.zmin))};a.THistPainter.prototype.getValueColor=function(d,g){var e=this.getContourIndex(d);if(e<0){return null}var c=this.GetPalette();var f=Math.floor((e+0.99)*c.length/(this.fContour.length-1));if(f>c.length-1){f=c.length-1}return g?f:c[f]};a.THistPainter.prototype.GetPalette=function(c){if(!this.fPalette||c){this.fPalette=a.Painter.GetColorPalette(this.options.Palette)}return this.fPalette};a.THistPainter.prototype.FillPaletteMenu=function(e){var d=this.options.Palette;if((d===null)||(d===0)){d=a.gStyle.Palette}function f(g){this.options.Palette=parseInt(g);this.GetPalette(true);this.Redraw()}function c(i,g,h){e.addchk((i===d)||h,""+g+"",i,f)}e.add("sub:Palette");c(50,"ROOT 5",(d>=10)&&(d<51));c(51,"Deep Sea");c(52,"Grayscale",(d>0)&&(d<10));c(53,"Dark body radiator");c(54,"Two-color hue");c(55,"Rainbow");c(56,"Inverted dark body radiator");c(57,"Bird",(d>112));c(58,"Cubehelix");c(59,"Green Red Violet");c(60,"Blue Red Yellow");c(61,"Ocean");c(62,"Color Printable On Grey");c(63,"Alpine");c(64,"Aquamarine");c(65,"Army");c(66,"Atlantic");e.add("endsub:")};a.THistPainter.prototype.DrawColorPalette=function(g,j,i){var d=this.FindFunction("TPaletteAxis"),f=this.FindPainterFor(d);if(this._can_move_colz){i=true;delete this._can_move_colz}if(!f&&!d){f=this.FindPainterFor(undefined,undefined,"TPaletteAxis");if(f){d=f.GetObject();this.AddFunction(d,true)}}if(!g){if(f){f.Enabled=false;f.RemoveDrawG()}return null}if(d===null){d=a.Create("TPave");a.extend(d,{_typename:"TPaletteAxis",fName:"TPave",fH:null,fAxis:null,fX1NDC:0.91,fX2NDC:0.95,fY1NDC:0.1,fY2NDC:0.9,fInit:1});d.fAxis=a.Create("TGaxis");a.extend(d.fAxis,{fTitle:this.GetObject().fZaxis.fTitle,fLineColor:1,fLineSyle:1,fLineWidth:1,fTextAngle:0,fTextSize:0.04,fTextAlign:11,fTextColor:1,fTextFont:42});this.AddFunction(d,true);i=true}var e=this.frame_painter();if(i){d.fX2NDC=e.fX2NDC+0.01+(d.fX2NDC-d.fX1NDC);d.fX1NDC=e.fX2NDC+0.01;d.fY1NDC=e.fY1NDC;d.fY2NDC=e.fY2NDC}var c="";if(j){c+=";postpone"}if(i&&!this.do_redraw_palette){c+=";canmove"}if(f===null){var h=this.CurrentPadName(this.pad_name);f=a.draw(this.divid,d,c);this.CurrentPadName(h)}else{f.Enabled=true;f.DrawPave(c)}f.Redraw=function(){};if((d.fX1NDC-0.0050){this.options.Zscale=0}else{this.options.Zscale=1}this.DrawColorPalette(this.options.Zscale>0,false,true)};a.TH2Painter=function(c){a.THistPainter.call(this,c);this.fContour=null;this.fCustomContour=false;this.fPalette=null};a.TH2Painter.prototype=Object.create(a.THistPainter.prototype);a.TH2Painter.prototype.FillHistContextMenu=function(c){c.add("Auto zoom-in",this.AutoZoom);c.addDrawMenu("Draw with",["col","colz","scat","box","text","lego","lego0","lego1","lego2","lego3","lego4"],function(d){this.options=this.DecodeOptions(d);this.Redraw()});if(this.options.Color>0){this.FillPaletteMenu(c)}};a.TH2Painter.prototype.ButtonClick=function(c){if(a.THistPainter.prototype.ButtonClick.call(this,c)){return true}if(this!==this.main_painter()){return false}switch(c){case"ToggleColor":this.ToggleColor();break;case"ToggleColorZ":if(this.options.Lego===12||this.options.Lego===14||this.options.Color>0){this.ToggleColz()}break;case"Toggle3D":if(this.options.Lego>0){this.options.Lego=0}else{if((this.nbinsx>=50)||(this.nbinsy>=50)){this.options.Lego=(this.options.Color>0)?14:13}else{this.options.Lego=(this.options.Color>0)?12:1}this.options.Zero=1}this.RedrawPad();break;default:return false}return true};a.TH2Painter.prototype.FillToolbar=function(){a.THistPainter.prototype.FillToolbar.call(this);var c=this.pad_painter(true);if(c===null){return}c.AddButton(a.ToolbarIcons.th2color,"Toggle color","ToggleColor");c.AddButton(a.ToolbarIcons.th2colorz,"Toggle color palette","ToggleColorZ");c.AddButton(a.ToolbarIcons.th2draw3d,"Toggle 3D mode","Toggle3D")};a.TH2Painter.prototype.ToggleColor=function(){var c=true;if(this.options.Lego>0){this.options.Lego=0;c=false}if(this.options.Color==0){this.options.Color=("LastColor" in this.options)?this.options.LastColor:1}else{if(c){this.options.LastColor=this.options.Color;this.options.Color=0}}this._can_move_colz=true;this.Redraw()};a.TH2Painter.prototype.AutoZoom=function(){var k=this.GetSelectIndex("x","left",-1),h=this.GetSelectIndex("x","right",1),v=this.GetSelectIndex("y","left",-1),u=this.GetSelectIndex("y","right",1),s,o,p=this.GetObject();if((k==h)||(v==u)){return}var m=p.getBinContent(k+1,v+1);for(s=k;s0){return}var f=h,e=k,c=u,l=v;for(s=k;sm){if(s=e){e=s+1}if(o=l){l=o+1}}}}var d,r,t,g,q=false;if((f>k||ev||lthis.gmaxbin){this.gmaxbin=f}}if(f>0){if((this.gmin0bin===null)||(this.gmin0bin>f)){this.gmin0bin=f}}}}if(this.gmin0bin===null){this.gmin0bin=this.gmaxbin*0.0001}this.draw_content=this.gmaxbin>0;if(this.is_main_painter()&&(this.zoom_xmin===this.zoom_xmax)&&this.histo.fXaxis.TestBit(a.EAxisBits.kAxisRange)&&(this.histo.fXaxis.fFirst!==this.histo.fXaxis.fLast)&&((this.histo.fXaxis.fFirst>1)||(this.histo.fXaxis.fLast<=this.nbinsx))){this.zoom_xmin=this.histo.fXaxis.fFirst>1?this.GetBinX(this.histo.fXaxis.fFirst-1):this.xmin;this.zoom_xmax=this.histo.fXaxis.fLast<=this.nbinsx?this.GetBinX(this.histo.fXaxis.fLast):this.xmax}if(this.is_main_painter()&&(this.zoom_ymin===this.zoom_ymax)&&this.histo.fYaxis.TestBit(a.EAxisBits.kAxisRange)&&(this.histo.fYaxis.fFirst!==this.histo.fYaxis.fLast)&&((this.histo.fYaxis.fFirst>1)||(this.histo.fYaxis.fLast<=this.nbinsy))){this.zoom_ymin=this.histo.fYaxis.fFirst>1?this.GetBinY(this.histo.fYaxis.fFirst-1):this.ymin;this.zoom_ymax=this.histo.fYaxis.fLast<=this.nbinsy?this.GetBinY(this.histo.fYaxis.fLast):this.ymax}};a.TH2Painter.prototype.CountStat=function(i){var j=this.GetObject(),e=0,h=0,p=0,g=0,o=0,s=0,d=this.GetSelectIndex("x","left"),m=this.GetSelectIndex("x","right"),t=this.GetSelectIndex("y","left"),r=this.GetSelectIndex("y","right"),l,c,f,v,q,k,u,w={entries:0,integral:0,meanx:0,meany:0,rmsx:0,rmsy:0,matrix:[0,0,0,0,0,0,0,0,0],xmax:0,ymax:0,wmax:null};for(l=0;l<=this.nbinsx+1;++l){c=(l<=d)?0:(l>m?2:1);f=this.GetBinX(l-0.5);for(v=0;v<=this.nbinsy+1;++v){q=(v<=t)?0:(v>r?2:1);k=this.GetBinY(v-0.5);u=j.getBinContent(l,v);w.entries+=u;w.matrix[q*3+c]+=u;if((c!=1)||(q!=1)){continue}if((i!=null)&&!i(f,k)){continue}if((w.wmax==null)||(u>w.wmax)){w.wmax=u;w.xmax=f;w.ymax=k}e+=u;h+=f*u;p+=k*u;g+=f*f*u;o+=k*k*u;s+=f*k*u}}if(!this.IsAxisZoomed("x")&&!this.IsAxisZoomed("y")&&(j.fTsumw>0)){e=j.fTsumw;h=j.fTsumwx;g=j.fTsumwx2;p=j.fTsumwy;o=j.fTsumwy2;s=j.fTsumwxy}if(e>0){w.meanx=h/e;w.meany=p/e;w.rmsx=Math.sqrt(g/e-w.meanx*w.meanx);w.rmsy=Math.sqrt(o/e-w.meany*w.meany)}if(w.wmax===null){w.wmax=0}w.integral=e;if(j.fEntries>1){w.entries=j.fEntries}return w};a.TH2Painter.prototype.FillStatistic=function(i,k,u){if(this.GetObject()===null){return false}var j=i.GetObject(),h=this.CountStat(),p=Math.floor(k%10),s=Math.floor(k/10)%10,o=Math.floor(k/100)%10,r=Math.floor(k/1000)%10,c=Math.floor(k/10000)%10,d=Math.floor(k/100000)%10,f=Math.floor(k/1000000)%10,l=Math.floor(k/10000000)%10,g=Math.floor(k/100000000)%10;if(p>0){j.AddText(this.GetObject().fName)}if(s>0){j.AddText("Entries = "+i.Format(h.entries,"entries"))}if(o>0){j.AddText("Mean x = "+i.Format(h.meanx));j.AddText("Mean y = "+i.Format(h.meany))}if(r>0){j.AddText("Std Dev x = "+i.Format(h.rmsx));j.AddText("Std Dev y = "+i.Format(h.rmsy))}if(f>0){j.AddText("Integral = "+i.Format(h.matrix[4],"entries"))}if(l>0){j.AddText("Skewness x = ");j.AddText("Skewness y = ")}if(g>0){j.AddText("Kurt = ")}if((c>0)||(d>0)){var e=h.matrix;j.AddText(""+e[6].toFixed(0)+" | "+e[7].toFixed(0)+" | "+e[7].toFixed(0));j.AddText(""+e[3].toFixed(0)+" | "+e[4].toFixed(0)+" | "+e[5].toFixed(0));j.AddText(""+e[0].toFixed(0)+" | "+e[1].toFixed(0)+" | "+e[2].toFixed(0))}var q=j.fLines.arr.length,t=q*a.gStyle.StatFontSize;if(t<=0||3==(a.gStyle.StatFont%10)){t=0.25*q*a.gStyle.StatH;j.fY1NDC=0.93-t;j.fY2NDC=0.93}return true};a.TH2Painter.prototype.PrepareColorDraw=function(c,d){var g=this.GetObject(),e=this.root_pad(),k=this.main_painter(),h,f,p,o,m,q,l={i1:this.GetSelectIndex("x","left",0),i2:this.GetSelectIndex("x","right",1),j1:this.GetSelectIndex("y","left",0),j2:this.GetSelectIndex("y","right",1),min:0,max:0};l.grx=new Float32Array(l.i2+1);l.gry=new Float32Array(l.j2+1);if(d){c=true}for(h=l.i1;h<=l.i2;++h){p=this.GetBinX(h);if(k.logx&&(p<=0)){l.i1=h+1;continue}l.grx[h]=k.grx(p);if(c){l.grx[h]=Math.round(l.grx[h])}}for(f=l.j1;f<=l.j2;++f){o=this.GetBinY(f);if(k.logy&&(o<=0)){l.j1=f+1;continue}l.gry[f]=k.gry(o);if(c){l.gry[f]=Math.round(l.gry[f])}}m=g.getBinContent(l.i1+1,l.j1+1);this.maxbin=this.minbin=this.minposbin=null;for(h=l.i1;h0)&&((m0){if((this.minposbin===null)||(m0)){A=true;y=Math.log(this.maxbin);r=(this.minbin>0)?Math.log(this.minbin):y-10;if(r>=y){r=y-10}l=0.5/(y-r);t=0.5/(y-r)}else{l=0.5/(this.maxbin-this.minbin);t=0.5/(this.maxbin-this.minbin)}for(s=B.i1;s0)?Math.log(o):r)):this.maxbin-o;D=B.grx[s+1]-B.grx[s];g=B.gry[q]-B.gry[q+1];f=x*l*D;e=x*t*g;D=Math.max(Math.round(D-2*f),1);g=Math.max(Math.round(g-2*e),1);if(C[s]===undefined){C[s]=""}C[s]+="M"+Math.round(B.grx[s]+f)+","+Math.round(B.gry[q+1]+e)+"v"+g+"h"+D+"v-"+g+"z"}}for(s=0;s=0.001){A.whiskerm=this.GetBinY(o+0.5)}if(g/c<0.25&&(g+d)/c>=0.25){A.m25y=this.GetBinY(o+0.5)}if(g/c<0.5&&(g+d)/c>=0.5){A.median=this.GetBinY(o+0.5)}if(g/c<0.75&&(g+d)/c>=0.75){A.p25y=this.GetBinY(o+0.5)}if(g/c<0.999&&(g+d)/c>=0.999){A.whiskerp=this.GetBinY(o+0.5)}g+=d;f=this.GetBinY(o+0.5);v+=d*f}if(g>0){A.meany=v/g}A.iqr=A.p25y-A.m25y;if((A.m25y-1.5*A.iqr)>A.whsikerm){A.whiskerm=A.m25y-1.5*A.iqr}if((A.p25y+1.5*A.iqr)0){k=k*l.fBarWidth/1000}A.x1=Math.round(x-k/2);A.x2=Math.round(x+k/2);x=Math.round(x);A.y0=Math.round(e.gry(A.median));m+="M"+A.x1+","+A.y0+"h"+(A.x2-A.x1);A.y1=Math.round(e.gry(A.p25y));A.y2=Math.round(e.gry(A.m25y));m+="M"+A.x1+","+A.y1+"v"+(A.y2-A.y1)+"h"+(A.x2-A.x1)+"v-"+(A.y2-A.y1)+"z";A.yy1=Math.round(e.gry(A.whiskerp));A.yy2=Math.round(e.gry(A.whiskerm));m+="M"+x+","+A.y1+"v"+(A.yy1-A.y1);m+="M"+A.x1+","+A.yy1+"h"+(A.x2-A.x1);m+="M"+x+","+A.y2+"v"+(A.yy2-A.y2);m+="M"+A.x1+","+A.yy2+"h"+(A.x2-A.x1);for(o=0;o0&&this.GetBinY(o+0.5)0&&this.GetBinY(o+0.5)>A.whiskerp){r+=this.markeratt.create(x,this.GetBinY(o+0.5))}}t.candle.push(A)}if(m.length>0){this.draw_g.append("svg:path").attr("d",m).call(this.lineatt.func).call(this.fillatt.func)}if(r.length>0){this.draw_g.append("svg:path").attr("d",r).call(this.markeratt.func)}return t};a.TH2Painter.prototype.DrawBinsScatter=function(m,C){var r=this.GetObject(),G=this.PrepareColorDraw(true,true),H=[],F=[],E=[],f=[],l=[],k,e,c,B,z,q,g,o,s=1;if(this.maxbin>0.7){s=0.7/this.maxbin}var y=Math.round(G.max-G.min);this.CreateContour((y>50)?50:y,this.minposbin,this.maxbin,this.minposbin);for(B=G.i1;B0)){d=I.insert("svg:defs",":first-child")}if(!this.markeratt){this.markeratt=a.Painter.createAttMarker(r)}for(k=0;k0){e=this.DrawBinsColor(c,d)}else{if(this.options.Scat>0){e=this.DrawBinsScatter(c,d)}else{if(this.options.Box>0){e=this.DrawBinsBox(c,d)}else{if(this.options.Candle.length>0){e=this.DrawCandle(c,d)}}}}if(this.options.Text>0){e=this.DrawBinsText(c,d,e)}this.tt_handle=e};a.TH2Painter.prototype.GetBinTips=function(f,e){var d=[],c=this.main_painter();d.push(this.GetTipName());if(this.x_kind=="labels"){d.push("x = "+c.AxisAsText("x",this.GetBinX(f)))}else{d.push("x = ["+c.AxisAsText("x",this.GetBinX(f))+", "+c.AxisAsText("x",this.GetBinX(f+1))+")")}if(this.y_kind=="labels"){d.push("y = "+c.AxisAsText("y",this.GetBinY(e)))}else{d.push("y = ["+c.AxisAsText("y",this.GetBinY(e))+", "+c.AxisAsText("y",this.GetBinY(e+1))+")")}d.push("bin = "+f+", "+e);var g=this.GetObject().getBinContent(f+1,e+1);if(g===Math.round(g)){d.push("entries = "+g)}else{d.push("entries = "+a.FFormat(g,a.gStyle.StatFormat))}return d};a.TH2Painter.prototype.GetCandleTips=function(e){var d=[],c=this.main_painter();d.push(this.GetTipName());d.push("x = "+c.AxisAsText("x",this.GetBinX(e.bin)));d.push("mean y = "+a.FFormat(e.meany,a.gStyle.StatFormat));d.push("m25 = "+a.FFormat(e.m25y,a.gStyle.StatFormat));d.push("p25 = "+a.FFormat(e.p25y,a.gStyle.StatFormat));return d};a.TH2Painter.prototype.ProcessTooltip=function(c){if((c==null)||!this.draw_content||!this.draw_g){if(this.draw_g!==null){this.draw_g.select(".tooltip_bin").remove()}this.ProvideUserTooltip(null);return null}var g=this.GetObject(),l=this.tt_handle,k,e=this.draw_g.select(".tooltip_bin");if(l.candle){var d;for(k=0;k=l.candle.length){e.remove();this.ProvideUserTooltip(null);return null}var o={x:c.x,y:c.y,color1:this.lineatt.color,color2:this.fillatt.color,lines:this.GetCandleTips(d),exact:true,menu:true};if(e.empty()){e=this.draw_g.append("svg:rect").attr("class","tooltip_bin h1bin").style("pointer-events","none")}o.changed=e.property("current_bin")!==k;if(o.changed){e.attr("x",d.x1).attr("width",d.x2-d.x1).attr("y",d.yy1).attr("height",d.yy2-d.yy1).style("opacity","0.7").property("current_bin",k)}if(this.IsUserTooltipCallback()&&o.changed){this.ProvideUserTooltip({obj:g,name:g.fName,bin:k+1,cont:d.median,binx:k+1,biny:1,grx:c.x,gry:c.y})}return o}var k,f,m=0;for(k=l.i1;k=l.grx[k])&&(c.x<=l.grx[k+1])){++m;break}}for(f=l.j1;f<=l.j2;++f){if((c.y>=l.gry[f+1])&&(c.y<=l.gry[f])){++m;break}}var q=(m===2)?g.getBinContent(k+1,f+1):0;var r=(m===2)?this.getValueColor(q,true):null;if((m!==2)||(r===null)){e.remove();this.ProvideUserTooltip(null);return null}var o={x:c.x,y:c.y,color1:this.lineatt.color,color2:this.fillatt.color,lines:this.GetBinTips(k,f),exact:true,menu:true};if(this.options.Color>0){o.color2=this.getValueColor(q)}if(e.empty()){e=this.draw_g.append("svg:rect").attr("class","tooltip_bin h1bin").style("pointer-events","none")}o.changed=e.property("current_bin")!==k*10000+f;if(o.changed){e.attr("x",l.grx[k]).attr("width",l.grx[k+1]-l.grx[k]).attr("y",l.gry[f+1]).attr("height",l.gry[f]-l.gry[f+1]).style("opacity","0.7").property("current_bin",k*10000+f)}if(this.IsUserTooltipCallback()&&o.changed){this.ProvideUserTooltip({obj:g,name:g.fName,bin:g.getBin(k+1,f+1),cont:q,binx:k+1,biny:f+1,grx:c.x,gry:c.y})}return o};a.TH2Painter.prototype.CanZoomIn=function(e,d,c){if((e=="x")&&(this.GetIndexX(c,0.5)-this.GetIndexX(d,0)>1)){return true}if((e=="y")&&(this.GetIndexY(c,0.5)-this.GetIndexY(d,0)>1)){return true}if(e=="z"){return true}return false};a.TH2Painter.prototype.Draw2D=function(e,d){if(typeof this.Create3DScene=="function"){this.Create3DScene(-1)}var c=this.DrawColorPalette((this.options.Zscale>0)&&(this.options.Color>0),true);this.DrawAxes();this.DrawGrids();this.DrawBins();if(c){c.DrawPave()}this.DrawTitle();this.AddInteractive();a.CallBack(e)};a.TH2Painter.prototype.Draw3D=function(c){a.AssertPrerequisites("3d",function(){this.Create3DScene=a.Painter.HPainter_Create3DScene;this.Draw3D=a.Painter.TH2Painter_Draw3D;this.Draw3D(c)}.bind(this))};a.TH2Painter.prototype.Redraw=function(d){this.CreateXY();var c=(this.options.Lego>0)?"Draw3D":"Draw2D";this[c](null,d)};a.Painter.drawHistogram2D=function(f,d,e){a.extend(this,new a.TH2Painter(d));this.SetDivId(f,1);this.options=this.DecodeOptions(e);this._can_move_colz=true;this.CheckPadRange();this.ScanContent();this.CreateXY();if(a.gStyle.AutoStat&&this.create_canvas){this.CreateStat()}var c=(this.options.Lego>0)?"Draw3D":"Draw2D";this[c](function(){this.DrawNextFunction(0,function(){if(this.options.Lego==0){if(this.options.AutoZoom){this.AutoZoom()}}this.FillToolbar();this.DrawingReady()}.bind(this))}.bind(this));return this};return a.Painter})); \ No newline at end of file diff --git a/visualisations/JsRoot460/scripts/ThreeCSG.js b/visualisations/JsRoot460/scripts/ThreeCSG.js new file mode 100644 index 0000000..27b83bf --- /dev/null +++ b/visualisations/JsRoot460/scripts/ThreeCSG.js @@ -0,0 +1,833 @@ + +function ThreeBSPfactory() { + + var ThreeBSP, + EPSILON = 1e-5, + COPLANAR = 0, + FRONT = 1, + BACK = 2, + SPANNING = 3; + + ThreeBSP = function( geometry, transfer_matrix, nodeid ) { + // Convert THREE.Geometry to ThreeBSP + var i, _length_i, + face, vertex, /* faceVertexUvs, uvs, */ + polygon, + polygons = [], + tree; + + if ( geometry instanceof THREE.Geometry ) { + this.matrix = null; // new THREE.Matrix4; not create matrix when do not needed + } else if ( geometry instanceof THREE.Mesh ) { + // #todo: add hierarchy support + geometry.updateMatrix(); + transfer_matrix = this.matrix = geometry.matrix.clone(); + geometry = geometry.geometry; + } else if ( geometry instanceof ThreeBSP.Node ) { + this.tree = geometry; + this.matrix = null; // new THREE.Matrix4; + return this; + } else if ( geometry instanceof THREE.BufferGeometry ) { + var pos_buf = geometry.getAttribute('position').array, + norm_buf = geometry.getAttribute('normal').array; + + for (var i=0; i < pos_buf.length; i+=9) { + polygon = new ThreeBSP.Polygon; + + vertex = new ThreeBSP.Vertex( pos_buf[i], pos_buf[i+1], pos_buf[i+2], norm_buf[i], norm_buf[i+1], norm_buf[i+2]); + if (transfer_matrix) vertex.applyMatrix4(transfer_matrix); + polygon.vertices.push( vertex ); + + vertex = new ThreeBSP.Vertex( pos_buf[i+3], pos_buf[i+4], pos_buf[i+5], norm_buf[i+3], norm_buf[i+4], norm_buf[i+5]); + if (transfer_matrix) vertex.applyMatrix4(transfer_matrix); + polygon.vertices.push( vertex ); + + vertex = new ThreeBSP.Vertex( pos_buf[i+6], pos_buf[i+7], pos_buf[i+8], norm_buf[i+6], norm_buf[i+7], norm_buf[i+8]); + if (transfer_matrix) vertex.applyMatrix4(transfer_matrix); + polygon.vertices.push( vertex ); + + polygon.calculateProperties(); + polygons.push( polygon ); + } + + this.tree = new ThreeBSP.Node( polygons, nodeid ); + if (nodeid!==undefined) this.maxid = this.tree.maxnodeid; + return this; + + } else if (geometry.polygons && (geometry.polygons[0] instanceof ThreeBSP.Polygon)) { + polygons = geometry.polygons; + + // console.log('create from direct polygons size ' + polygons.length); + + for (var i=0;i 1); + + while (foundpair) { + foundpair = false; + + for (i1 = 0; i10) { + polygons.splice(0, polygons.length); + + for(n=0;n 0 ) { + this.calculateProperties(); + } else { + this.normal = this.w = undefined; + } + }; + ThreeBSP.Polygon.prototype.copyProperties = function(parent, more) { + this.normal = parent.normal; // .clone(); + this.w = parent.w; + this.nsign = parent.nsign; + if (more && (parent.id !== undefined)) { + this.id = parent.id; + this.parent = parent; + } + return this; + }; + ThreeBSP.Polygon.prototype.calculateProperties = function() { + if (this.normal) return; + + var a = this.vertices[0], + b = this.vertices[1], + c = this.vertices[2]; + + this.nsign = 1; + + this.normal = b.clone().subtract( a ).cross( + c.clone().subtract( a ) + ).normalize(); + + this.w = this.normal.clone().dot( a ); + return this; + }; + ThreeBSP.Polygon.prototype.clone = function() { + var i, vertice_count, + polygon = new ThreeBSP.Polygon; + + for ( i = 0, vertice_count = this.vertices.length; i < vertice_count; ++i ) { + polygon.vertices.push( this.vertices[i].clone() ); + }; + return polygon.copyProperties(this); + }; + + ThreeBSP.Polygon.prototype.flip = function() { + + /// normal is not changed, only sign variable + //this.normal.multiplyScalar( -1 ); + //this.w *= -1; + + this.nsign *= -1; + + this.vertices.reverse(); + + return this; + }; + + ThreeBSP.Polygon.prototype.classifyVertex = function( vertex ) { + var side_value = this.nsign * (this.normal.dot( vertex ) - this.w); + + if ( side_value < -EPSILON ) { + return BACK; + } else if ( side_value > EPSILON ) { + return FRONT; + } else { + return COPLANAR; + } + }; + ThreeBSP.Polygon.prototype.classifySide = function( polygon ) { + var i, classification, + num_positive = 0, num_negative = 0, + vertice_count = polygon.vertices.length; + + for ( i = 0; i < vertice_count; ++i ) { + classification = this.classifyVertex( polygon.vertices[i] ); + if ( classification === FRONT ) { + ++num_positive; + } else if ( classification === BACK ) { + ++num_negative; + } + } + + if ( num_positive > 0 && num_negative === 0 ) { + return FRONT; + } else if ( num_positive === 0 && num_negative > 0 ) { + return BACK; + } else if ( num_positive === 0 && num_negative === 0 ) { + return COPLANAR; + } else { + return SPANNING; + } + }; + ThreeBSP.Polygon.prototype.splitPolygon = function( polygon, coplanar_front, coplanar_back, front, back ) { + var classification = this.classifySide( polygon ); + + if ( classification === COPLANAR ) { + + ( (this.nsign * polygon.nsign * this.normal.dot( polygon.normal ) > 0) ? coplanar_front : coplanar_back ).push( polygon ); + + } else if ( classification === FRONT ) { + + front.push( polygon ); + + } else if ( classification === BACK ) { + + back.push( polygon ); + + } else { + + var vertice_count = polygon.vertices.length, + nnx = this.normal.x, + nny = this.normal.y, + nnz = this.normal.z, + i, j, ti, tj, vi, vj, + t, v, + f = [], b = []; + + for ( i = 0; i < vertice_count; ++i ) { + + j = (i + 1) % vertice_count; + vi = polygon.vertices[i]; + vj = polygon.vertices[j]; + ti = this.classifyVertex( vi ); + tj = this.classifyVertex( vj ); + + if ( ti != BACK ) f.push( vi ); + if ( ti != FRONT ) b.push( vi ); + if ( (ti | tj) === SPANNING ) { + // t = ( this.w - this.normal.dot( vi ) ) / this.normal.dot( vj.clone().subtract( vi ) ); + //v = vi.clone().lerp( vj, t ); + + t = (this.w - (nnx*vi.x + nny*vi.y + nnz*vi.z)) / (nnx*(vj.x-vi.x) + nny*(vj.y-vi.y) + nnz*(vj.z-vi.z)); + + v = vi.interpolate( vj, t ); + f.push( v ); + b.push( v ); + } + } + + //if ( f.length >= 3 ) front.push( new ThreeBSP.Polygon( f ).calculateProperties() ); + //if ( b.length >= 3 ) back.push( new ThreeBSP.Polygon( b ).calculateProperties() ); + if ( f.length >= 3 ) front.push( new ThreeBSP.Polygon( f ).copyProperties(polygon, true) ); + if ( b.length >= 3 ) back.push( new ThreeBSP.Polygon( b ).copyProperties(polygon, true) ); + } + }; + + ThreeBSP.Vertex = function( x, y, z, nx,ny, nz /* normal , uv */ ) { + this.x = x; + this.y = y; + this.z = z; + this.nx = nx; + this.ny = ny; + this.nz = nz; + // this.uv = uv || new THREE.Vector2; + }; + + ThreeBSP.Vertex.prototype.setnormal = function ( nx, ny, nz ) { + this.nx = nx; + this.ny = ny; + this.nz = nz; + }; + + ThreeBSP.Vertex.prototype.clone = function() { + return new ThreeBSP.Vertex( this.x, this.y, this.z, this.nx, this.ny, this.nz); + }; + ThreeBSP.Vertex.prototype.add = function( vertex ) { + this.x += vertex.x; + this.y += vertex.y; + this.z += vertex.z; + return this; + }; + ThreeBSP.Vertex.prototype.subtract = function( vertex ) { + this.x -= vertex.x; + this.y -= vertex.y; + this.z -= vertex.z; + return this; + }; + ThreeBSP.Vertex.prototype.multiplyScalar = function( scalar ) { + this.x *= scalar; + this.y *= scalar; + this.z *= scalar; + return this; + }; + ThreeBSP.Vertex.prototype.cross = function( vertex ) { + var x = this.x, + y = this.y, + z = this.z; + + this.x = y * vertex.z - z * vertex.y; + this.y = z * vertex.x - x * vertex.z; + this.z = x * vertex.y - y * vertex.x; + + return this; + }; + ThreeBSP.Vertex.prototype.normalize = function() { + var length = Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z ); + + this.x /= length; + this.y /= length; + this.z /= length; + + return this; + }; + ThreeBSP.Vertex.prototype.dot = function( vertex ) { + return this.x * vertex.x + this.y * vertex.y + this.z * vertex.z; + }; + + ThreeBSP.Vertex.prototype.diff = function( vertex ) { + var dx = (this.x - vertex.x), + dy = (this.y - vertex.y), + dz = (this.z - vertex.z), + len2 = this.x * this.x + this.y * this.y + this.z * this.z; + + return (dx*dx+dy*dy+dz*dz) / (len2>0 ? len2 : 1e-10); + }; + +/* + ThreeBSP.Vertex.prototype.lerp = function( a, t ) { + this.add( + a.clone().subtract( this ).multiplyScalar( t ) + ); + + this.normal.add( + a.normal.clone().sub( this.normal ).multiplyScalar( t ) + ); + + //this.uv.add( + // a.uv.clone().sub( this.uv ).multiplyScalar( t ) + //); + + return this; + }; + ThreeBSP.Vertex.prototype.interpolate = function( other, t ) { + return this.clone().lerp( other, t ); + }; +*/ + + ThreeBSP.Vertex.prototype.interpolate = function( a, t ) { + var t1 = 1-t; + return new ThreeBSP.Vertex(this.x*t1 + a.x*t, this.y*t1 + a.y*t, this.z*t1 + a.z*t, + this.nx*t1 + a.nx*t, this.ny*t1 + a.ny*t, this.nz*t1 + a.nz*t); + }; + + ThreeBSP.Vertex.prototype.applyMatrix4 = function ( m ) { + + // input: THREE.Matrix4 affine matrix + + var x = this.x, y = this.y, z = this.z, e = m.elements; + + this.x = e[0] * x + e[4] * y + e[8] * z + e[12]; + this.y = e[1] * x + e[5] * y + e[9] * z + e[13]; + this.z = e[2] * x + e[6] * y + e[10] * z + e[14]; + + x = this.nx; y = this.ny; z = this.nz; + + this.nx = e[0] * x + e[4] * y + e[8] * z; + this.ny = e[1] * x + e[5] * y + e[9] * z; + this.nz = e[2] * x + e[6] * y + e[10] * z; + + return this; + } + + + ThreeBSP.Node = function( polygons, nodeid ) { + var i, polygon_count, + front = [], + back = []; + + this.polygons = []; + this.front = this.back = undefined; + + if ( !(polygons instanceof Array) || polygons.length === 0 ) return; + + this.divider = polygons[0].clone(); + + for ( i = 0, polygon_count = polygons.length; i < polygon_count; ++i ) { + if (nodeid!==undefined) { + polygons[i].id = nodeid++; + delete polygons[i].parent; + } + + this.divider.splitPolygon( polygons[i], this.polygons, this.polygons, front, back ); + } + + if (nodeid !== undefined) this.maxnodeid = nodeid; + + if ( front.length > 0 ) { + this.front = new ThreeBSP.Node( front ); + } + + if ( back.length > 0 ) { + this.back = new ThreeBSP.Node( back ); + } + }; + ThreeBSP.Node.isConvex = function( polygons ) { + var i, j, len = polygons.length; + for ( i = 0; i < len; ++i ) { + for ( j = 0; j < len; ++j ) { + if ( i !== j && polygons[i].classifySide( polygons[j] ) !== BACK ) { + return false; + } + } + } + return true; + }; + ThreeBSP.Node.prototype.build = function( polygons ) { + var i, polygon_count, + front = [], + back = []; + + if ( !this.divider ) { + this.divider = polygons[0].clone(); + } + + for ( i = 0, polygon_count = polygons.length; i < polygon_count; ++i ) { + this.divider.splitPolygon( polygons[i], this.polygons, this.polygons, front, back ); + } + + if ( front.length > 0 ) { + if ( !this.front ) this.front = new ThreeBSP.Node(); + this.front.build( front ); + } + + if ( back.length > 0 ) { + if ( !this.back ) this.back = new ThreeBSP.Node(); + this.back.build( back ); + } + }; + + ThreeBSP.Node.prototype.collectPolygons = function(arr) { + var i, len = this.polygons.length; + for (i=0;i1);while(i){i=false;for(k=0;k0){r.splice(0,r.length);for(h=0;h0){this.calculateProperties()}else{this.normal=this.w=undefined}};f.Polygon.prototype.copyProperties=function(h,g){this.normal=h.normal;this.w=h.w;this.nsign=h.nsign;if(g&&(h.id!==undefined)){this.id=h.id;this.parent=h}return this};f.Polygon.prototype.calculateProperties=function(){if(this.normal){return}var h=this.vertices[0],g=this.vertices[1],i=this.vertices[2];this.nsign=1;this.normal=g.clone().subtract(h).cross(i.clone().subtract(h)).normalize();this.w=this.normal.clone().dot(h);return this};f.Polygon.prototype.clone=function(){var j,g,h=new f.Polygon;for(j=0,g=this.vertices.length;jb){return c}else{return d}}};f.Polygon.prototype.classifySide=function(k){var j,l,m=0,h=0,g=k.vertices.length;for(j=0;j0&&h===0){return c}else{if(m===0&&h>0){return e}else{if(m===0&&h===0){return d}else{return a}}}};f.Polygon.prototype.splitPolygon=function(o,z,m,l,q){var g=this.classifySide(o);if(g===d){((this.nsign*o.nsign*this.normal.dot(o.normal)>0)?z:m).push(o)}else{if(g===c){l.push(o)}else{if(g===e){q.push(o)}else{var D=o.vertices.length,u=this.normal.x,s=this.normal.y,r=this.normal.z,x,w,k,h,C,B,p,n,y=[],A=[];for(x=0;x=3){l.push(new f.Polygon(y).copyProperties(o,true))}if(A.length>=3){q.push(new f.Polygon(A).copyProperties(o,true))}}}}};f.Vertex=function(h,l,j,g,k,i){this.x=h;this.y=l;this.z=j;this.nx=g;this.ny=k;this.nz=i};f.Vertex.prototype.setnormal=function(g,i,h){this.nx=g;this.ny=i;this.nz=h};f.Vertex.prototype.clone=function(){return new f.Vertex(this.x,this.y,this.z,this.nx,this.ny,this.nz)};f.Vertex.prototype.add=function(g){this.x+=g.x;this.y+=g.y;this.z+=g.z;return this};f.Vertex.prototype.subtract=function(g){this.x-=g.x;this.y-=g.y;this.z-=g.z;return this};f.Vertex.prototype.multiplyScalar=function(g){this.x*=g;this.y*=g;this.z*=g;return this};f.Vertex.prototype.cross=function(h){var g=this.x,j=this.y,i=this.z;this.x=j*h.z-i*h.y;this.y=i*h.x-g*h.z;this.z=g*h.y-j*h.x;return this};f.Vertex.prototype.normalize=function(){var g=Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z);this.x/=g;this.y/=g;this.z/=g;return this};f.Vertex.prototype.dot=function(g){return this.x*g.x+this.y*g.y+this.z*g.z};f.Vertex.prototype.diff=function(k){var j=(this.x-k.x),h=(this.y-k.y),g=(this.z-k.z),i=this.x*this.x+this.y*this.y+this.z*this.z;return(j*j+h*h+g*g)/(i>0?i:1e-10)};f.Vertex.prototype.interpolate=function(g,h){var i=1-h;return new f.Vertex(this.x*i+g.x*h,this.y*i+g.y*h,this.z*i+g.z*h,this.nx*i+g.nx*h,this.ny*i+g.ny*h,this.nz*i+g.nz*h)};f.Vertex.prototype.applyMatrix4=function(h){var g=this.x,k=this.y,j=this.z,i=h.elements;this.x=i[0]*g+i[4]*k+i[8]*j+i[12];this.y=i[1]*g+i[5]*k+i[9]*j+i[13];this.z=i[2]*g+i[6]*k+i[10]*j+i[14];g=this.nx;k=this.ny;j=this.nz;this.nx=i[0]*g+i[4]*k+i[8]*j;this.ny=i[1]*g+i[5]*k+i[9]*j;this.nz=i[2]*g+i[6]*k+i[10]*j;return this};f.Node=function(g,l){var j,m,k=[],h=[];this.polygons=[];this.front=this.back=undefined;if(!(g instanceof Array)||g.length===0){return}this.divider=g[0].clone();for(j=0,m=g.length;j0){this.front=new f.Node(k)}if(h.length>0){this.back=new f.Node(h)}};f.Node.isConvex=function(h){var l,k,g=h.length;for(l=0;l0){if(!this.front){this.front=new f.Node()}this.front.build(k)}if(h.length>0){if(!this.back){this.back=new f.Node()}this.back.build(h)}};f.Node.prototype.collectPolygons=function(h){var j,g=this.polygons.length;for(j=0;jn?-1:n>t?1:n>=t?0:NaN}function r(n){return null===n?NaN:+n}function u(n){return!isNaN(n)}function i(n){return{left:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;n(t[i],e)<0?r=i+1:u=i}return r},right:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;n(t[i],e)>0?u=i:r=i+1}return r}}}function a(n){return n.length}function o(n){for(var t=1;n*t%1;)t*=10;return t}function l(n,t){for(var e in t)Object.defineProperty(n.prototype,e,{value:t[e],enumerable:!1})}function c(){this._=Object.create(null)}function s(n){return(n+="")===xa||n[0]===ba?ba+n:n}function f(n){return(n+="")[0]===ba?n.slice(1):n}function h(n){return s(n)in this._}function g(n){return(n=s(n))in this._&&delete this._[n]}function p(){var n=[];for(var t in this._)n.push(f(t));return n}function v(){var n=0;for(var t in this._)++n;return n}function d(){for(var n in this._)return!1;return!0}function m(){this._=Object.create(null)}function y(n){return n}function M(n,t,e){return function(){var r=e.apply(t,arguments);return r===t?n:r}}function x(n,t){if(t in n)return t;t=t.charAt(0).toUpperCase()+t.slice(1);for(var e=0,r=_a.length;r>e;++e){var u=_a[e]+t;if(u in n)return u}}function b(){}function _(){}function w(n){function t(){for(var t,r=e,u=-1,i=r.length;++ue;e++)for(var u,i=n[e],a=0,o=i.length;o>a;a++)(u=i[a])&&t(u,a,e);return n}function Z(n){return Sa(n,za),n}function V(n){var t,e;return function(r,u,i){var a,o=n[i].update,l=o.length;for(i!=e&&(e=i,t=0),u>=t&&(t=u+1);!(a=o[t])&&++t0&&(n=n.slice(0,o));var c=La.get(n);return c&&(n=c,l=B),o?t?u:r:t?b:i}function $(n,t){return function(e){var r=oa.event;oa.event=e,t[0]=this.__data__;try{n.apply(this,t)}finally{oa.event=r}}}function B(n,t){var e=$(n,t);return function(n){var t=this,r=n.relatedTarget;r&&(r===t||8&r.compareDocumentPosition(t))||e.call(t,n)}}function W(e){var r=".dragsuppress-"+ ++Ta,u="click"+r,i=oa.select(t(e)).on("touchmove"+r,S).on("dragstart"+r,S).on("selectstart"+r,S);if(null==qa&&(qa="onselectstart"in e?!1:x(e.style,"userSelect")),qa){var a=n(e).style,o=a[qa];a[qa]="none"}return function(n){if(i.on(r,null),qa&&(a[qa]=o),n){var t=function(){i.on(u,null)};i.on(u,function(){S(),t()},!0),setTimeout(t,0)}}}function J(n,e){e.changedTouches&&(e=e.changedTouches[0]);var r=n.ownerSVGElement||n;if(r.createSVGPoint){var u=r.createSVGPoint();if(0>Ra){var i=t(n);if(i.scrollX||i.scrollY){r=oa.select("body").append("svg").style({position:"absolute",top:0,left:0,margin:0,padding:0,border:"none"},"important");var a=r[0][0].getScreenCTM();Ra=!(a.f||a.e),r.remove()}}return Ra?(u.x=e.pageX,u.y=e.pageY):(u.x=e.clientX,u.y=e.clientY),u=u.matrixTransform(n.getScreenCTM().inverse()),[u.x,u.y]}var o=n.getBoundingClientRect();return[e.clientX-o.left-n.clientLeft,e.clientY-o.top-n.clientTop]}function G(){return oa.event.changedTouches[0].identifier}function K(n){return n>0?1:0>n?-1:0}function Q(n,t,e){return(t[0]-n[0])*(e[1]-n[1])-(t[1]-n[1])*(e[0]-n[0])}function nn(n){return n>1?0:-1>n?ja:Math.acos(n)}function tn(n){return n>1?Ha:-1>n?-Ha:Math.asin(n)}function en(n){return((n=Math.exp(n))-1/n)/2}function rn(n){return((n=Math.exp(n))+1/n)/2}function un(n){return((n=Math.exp(2*n))-1)/(n+1)}function an(n){return(n=Math.sin(n/2))*n}function on(){}function ln(n,t,e){return this instanceof ln?(this.h=+n,this.s=+t,void(this.l=+e)):arguments.length<2?n instanceof ln?new ln(n.h,n.s,n.l):_n(""+n,wn,ln):new ln(n,t,e)}function cn(n,t,e){function r(n){return n>360?n-=360:0>n&&(n+=360),60>n?i+(a-i)*n/60:180>n?a:240>n?i+(a-i)*(240-n)/60:i}function u(n){return Math.round(255*r(n))}var i,a;return n=isNaN(n)?0:(n%=360)<0?n+360:n,t=isNaN(t)?0:0>t?0:t>1?1:t,e=0>e?0:e>1?1:e,a=.5>=e?e*(1+t):e+t-e*t,i=2*e-a,new yn(u(n+120),u(n),u(n-120))}function sn(n,t,e){return this instanceof sn?(this.h=+n,this.c=+t,void(this.l=+e)):arguments.length<2?n instanceof sn?new sn(n.h,n.c,n.l):n instanceof hn?pn(n.l,n.a,n.b):pn((n=Sn((n=oa.rgb(n)).r,n.g,n.b)).l,n.a,n.b):new sn(n,t,e)}function fn(n,t,e){return isNaN(n)&&(n=0),isNaN(t)&&(t=0),new hn(e,Math.cos(n*=Oa)*t,Math.sin(n)*t)}function hn(n,t,e){return this instanceof hn?(this.l=+n,this.a=+t,void(this.b=+e)):arguments.length<2?n instanceof hn?new hn(n.l,n.a,n.b):n instanceof sn?fn(n.h,n.c,n.l):Sn((n=yn(n)).r,n.g,n.b):new hn(n,t,e)}function gn(n,t,e){var r=(n+16)/116,u=r+t/500,i=r-e/200;return u=vn(u)*Ka,r=vn(r)*Qa,i=vn(i)*no,new yn(mn(3.2404542*u-1.5371385*r-.4985314*i),mn(-.969266*u+1.8760108*r+.041556*i),mn(.0556434*u-.2040259*r+1.0572252*i))}function pn(n,t,e){return n>0?new sn(Math.atan2(e,t)*Ia,Math.sqrt(t*t+e*e),n):new sn(NaN,NaN,n)}function vn(n){return n>.206893034?n*n*n:(n-4/29)/7.787037}function dn(n){return n>.008856?Math.pow(n,1/3):7.787037*n+4/29}function mn(n){return Math.round(255*(.00304>=n?12.92*n:1.055*Math.pow(n,1/2.4)-.055))}function yn(n,t,e){return this instanceof yn?(this.r=~~n,this.g=~~t,void(this.b=~~e)):arguments.length<2?n instanceof yn?new yn(n.r,n.g,n.b):_n(""+n,yn,cn):new yn(n,t,e)}function Mn(n){return new yn(n>>16,n>>8&255,255&n)}function xn(n){return Mn(n)+""}function bn(n){return 16>n?"0"+Math.max(0,n).toString(16):Math.min(255,n).toString(16)}function _n(n,t,e){var r,u,i,a=0,o=0,l=0;if(r=/([a-z]+)\((.*)\)/.exec(n=n.toLowerCase()))switch(u=r[2].split(","),r[1]){case"hsl":return e(parseFloat(u[0]),parseFloat(u[1])/100,parseFloat(u[2])/100);case"rgb":return t(Nn(u[0]),Nn(u[1]),Nn(u[2]))}return(i=ro.get(n))?t(i.r,i.g,i.b):(null==n||"#"!==n.charAt(0)||isNaN(i=parseInt(n.slice(1),16))||(4===n.length?(a=(3840&i)>>4,a=a>>4|a,o=240&i,o=o>>4|o,l=15&i,l=l<<4|l):7===n.length&&(a=(16711680&i)>>16,o=(65280&i)>>8,l=255&i)),t(a,o,l))}function wn(n,t,e){var r,u,i=Math.min(n/=255,t/=255,e/=255),a=Math.max(n,t,e),o=a-i,l=(a+i)/2;return o?(u=.5>l?o/(a+i):o/(2-a-i),r=n==a?(t-e)/o+(e>t?6:0):t==a?(e-n)/o+2:(n-t)/o+4,r*=60):(r=NaN,u=l>0&&1>l?0:r),new ln(r,u,l)}function Sn(n,t,e){n=kn(n),t=kn(t),e=kn(e);var r=dn((.4124564*n+.3575761*t+.1804375*e)/Ka),u=dn((.2126729*n+.7151522*t+.072175*e)/Qa),i=dn((.0193339*n+.119192*t+.9503041*e)/no);return hn(116*u-16,500*(r-u),200*(u-i))}function kn(n){return(n/=255)<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4)}function Nn(n){var t=parseFloat(n);return"%"===n.charAt(n.length-1)?Math.round(2.55*t):t}function En(n){return"function"==typeof n?n:function(){return n}}function An(n){return function(t,e,r){return 2===arguments.length&&"function"==typeof e&&(r=e,e=null),Cn(t,e,n,r)}}function Cn(n,t,e,r){function u(){var n,t=l.status;if(!t&&Ln(l)||t>=200&&300>t||304===t){try{n=e.call(i,l)}catch(r){return void a.error.call(i,r)}a.load.call(i,n)}else a.error.call(i,l)}var i={},a=oa.dispatch("beforesend","progress","load","error"),o={},l=new XMLHttpRequest,c=null;return!this.XDomainRequest||"withCredentials"in l||!/^(http(s)?:)?\/\//.test(n)||(l=new XDomainRequest),"onload"in l?l.onload=l.onerror=u:l.onreadystatechange=function(){l.readyState>3&&u()},l.onprogress=function(n){var t=oa.event;oa.event=n;try{a.progress.call(i,l)}finally{oa.event=t}},i.header=function(n,t){return n=(n+"").toLowerCase(),arguments.length<2?o[n]:(null==t?delete o[n]:o[n]=t+"",i)},i.mimeType=function(n){return arguments.length?(t=null==n?null:n+"",i):t},i.responseType=function(n){return arguments.length?(c=n,i):c},i.response=function(n){return e=n,i},["get","post"].forEach(function(n){i[n]=function(){return i.send.apply(i,[n].concat(ca(arguments)))}}),i.send=function(e,r,u){if(2===arguments.length&&"function"==typeof r&&(u=r,r=null),l.open(e,n,!0),null==t||"accept"in o||(o.accept=t+",*/*"),l.setRequestHeader)for(var s in o)l.setRequestHeader(s,o[s]);return null!=t&&l.overrideMimeType&&l.overrideMimeType(t),null!=c&&(l.responseType=c),null!=u&&i.on("error",u).on("load",function(n){u(null,n)}),a.beforesend.call(i,l),l.send(null==r?null:r),i},i.abort=function(){return l.abort(),i},oa.rebind(i,a,"on"),null==r?i:i.get(zn(r))}function zn(n){return 1===n.length?function(t,e){n(null==t?e:null)}:n}function Ln(n){var t=n.responseType;return t&&"text"!==t?n.response:n.responseText}function qn(n,t,e){var r=arguments.length;2>r&&(t=0),3>r&&(e=Date.now());var u=e+t,i={c:n,t:u,n:null};return io?io.n=i:uo=i,io=i,ao||(oo=clearTimeout(oo),ao=1,lo(Tn)),i}function Tn(){var n=Rn(),t=Dn()-n;t>24?(isFinite(t)&&(clearTimeout(oo),oo=setTimeout(Tn,t)),ao=0):(ao=1,lo(Tn))}function Rn(){for(var n=Date.now(),t=uo;t;)n>=t.t&&t.c(n-t.t)&&(t.c=null),t=t.n;return n}function Dn(){for(var n,t=uo,e=1/0;t;)t.c?(t.t8?function(n){return n/e}:function(n){return n*e},symbol:n}}function Un(n){var t=n.decimal,e=n.thousands,r=n.grouping,u=n.currency,i=r&&e?function(n,t){for(var u=n.length,i=[],a=0,o=r[0],l=0;u>0&&o>0&&(l+o+1>t&&(o=Math.max(1,t-l)),i.push(n.substring(u-=o,u+o)),!((l+=o+1)>t));)o=r[a=(a+1)%r.length];return i.reverse().join(e)}:y;return function(n){var e=so.exec(n),r=e[1]||" ",a=e[2]||">",o=e[3]||"-",l=e[4]||"",c=e[5],s=+e[6],f=e[7],h=e[8],g=e[9],p=1,v="",d="",m=!1,y=!0;switch(h&&(h=+h.substring(1)),(c||"0"===r&&"="===a)&&(c=r="0",a="="),g){case"n":f=!0,g="g";break;case"%":p=100,d="%",g="f";break;case"p":p=100,d="%",g="r";break;case"b":case"o":case"x":case"X":"#"===l&&(v="0"+g.toLowerCase());case"c":y=!1;case"d":m=!0,h=0;break;case"s":p=-1,g="r"}"$"===l&&(v=u[0],d=u[1]),"r"!=g||h||(g="g"),null!=h&&("g"==g?h=Math.max(1,Math.min(21,h)):("e"==g||"f"==g)&&(h=Math.max(0,Math.min(20,h)))),g=fo.get(g)||Fn;var M=c&&f;return function(n){var e=d;if(m&&n%1)return"";var u=0>n||0===n&&0>1/n?(n=-n,"-"):"-"===o?"":o;if(0>p){var l=oa.formatPrefix(n,h);n=l.scale(n),e=l.symbol+d}else n*=p;n=g(n,h);var x,b,_=n.lastIndexOf(".");if(0>_){var w=y?n.lastIndexOf("e"):-1;0>w?(x=n,b=""):(x=n.substring(0,w),b=n.substring(w))}else x=n.substring(0,_),b=t+n.substring(_+1);!c&&f&&(x=i(x,1/0));var S=v.length+x.length+b.length+(M?0:u.length),k=s>S?new Array(S=s-S+1).join(r):"";return M&&(x=i(k+x,k.length?s-b.length:1/0)),u+=v,n=x+b,("<"===a?u+n+k:">"===a?k+u+n:"^"===a?k.substring(0,S>>=1)+u+n+k.substring(S):u+(M?n:k+n))+e}}}function Fn(n){return n+""}function Hn(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function On(n,t,e){function r(t){var e=n(t),r=i(e,1);return r-t>t-e?e:r}function u(e){return t(e=n(new go(e-1)),1),e}function i(n,e){return t(n=new go(+n),e),n}function a(n,r,i){var a=u(n),o=[];if(i>1)for(;r>a;)e(a)%i||o.push(new Date(+a)),t(a,1);else for(;r>a;)o.push(new Date(+a)),t(a,1);return o}function o(n,t,e){try{go=Hn;var r=new Hn;return r._=n,a(r,t,e)}finally{go=Date}}n.floor=n,n.round=r,n.ceil=u,n.offset=i,n.range=a;var l=n.utc=In(n);return l.floor=l,l.round=In(r),l.ceil=In(u),l.offset=In(i),l.range=o,n}function In(n){return function(t,e){try{go=Hn;var r=new Hn;return r._=t,n(r,e)._}finally{go=Date}}}function Yn(n){function t(n){function t(t){for(var e,u,i,a=[],o=-1,l=0;++oo;){if(r>=c)return-1;if(u=t.charCodeAt(o++),37===u){if(a=t.charAt(o++),i=C[a in vo?t.charAt(o++):a],!i||(r=i(n,e,r))<0)return-1}else if(u!=e.charCodeAt(r++))return-1}return r}function r(n,t,e){_.lastIndex=0;var r=_.exec(t.slice(e));return r?(n.w=w.get(r[0].toLowerCase()),e+r[0].length):-1}function u(n,t,e){x.lastIndex=0;var r=x.exec(t.slice(e));return r?(n.w=b.get(r[0].toLowerCase()),e+r[0].length):-1}function i(n,t,e){N.lastIndex=0;var r=N.exec(t.slice(e));return r?(n.m=E.get(r[0].toLowerCase()),e+r[0].length):-1}function a(n,t,e){S.lastIndex=0;var r=S.exec(t.slice(e));return r?(n.m=k.get(r[0].toLowerCase()),e+r[0].length):-1}function o(n,t,r){return e(n,A.c.toString(),t,r)}function l(n,t,r){return e(n,A.x.toString(),t,r)}function c(n,t,r){return e(n,A.X.toString(),t,r)}function s(n,t,e){var r=M.get(t.slice(e,e+=2).toLowerCase());return null==r?-1:(n.p=r,e)}var f=n.dateTime,h=n.date,g=n.time,p=n.periods,v=n.days,d=n.shortDays,m=n.months,y=n.shortMonths;t.utc=function(n){function e(n){try{go=Hn;var t=new go;return t._=n,r(t)}finally{go=Date}}var r=t(n);return e.parse=function(n){try{go=Hn;var t=r.parse(n);return t&&t._}finally{go=Date}},e.toString=r.toString,e},t.multi=t.utc.multi=ct;var M=oa.map(),x=Vn(v),b=Xn(v),_=Vn(d),w=Xn(d),S=Vn(m),k=Xn(m),N=Vn(y),E=Xn(y);p.forEach(function(n,t){M.set(n.toLowerCase(),t)});var A={a:function(n){return d[n.getDay()]},A:function(n){return v[n.getDay()]},b:function(n){return y[n.getMonth()]},B:function(n){return m[n.getMonth()]},c:t(f),d:function(n,t){return Zn(n.getDate(),t,2)},e:function(n,t){return Zn(n.getDate(),t,2)},H:function(n,t){return Zn(n.getHours(),t,2)},I:function(n,t){return Zn(n.getHours()%12||12,t,2)},j:function(n,t){return Zn(1+ho.dayOfYear(n),t,3)},L:function(n,t){return Zn(n.getMilliseconds(),t,3)},m:function(n,t){return Zn(n.getMonth()+1,t,2)},M:function(n,t){return Zn(n.getMinutes(),t,2)},p:function(n){return p[+(n.getHours()>=12)]},S:function(n,t){return Zn(n.getSeconds(),t,2)},U:function(n,t){return Zn(ho.sundayOfYear(n),t,2)},w:function(n){return n.getDay()},W:function(n,t){return Zn(ho.mondayOfYear(n),t,2)},x:t(h),X:t(g),y:function(n,t){return Zn(n.getFullYear()%100,t,2)},Y:function(n,t){return Zn(n.getFullYear()%1e4,t,4)},Z:ot,"%":function(){return"%"}},C={a:r,A:u,b:i,B:a,c:o,d:tt,e:tt,H:rt,I:rt,j:et,L:at,m:nt,M:ut,p:s,S:it,U:Bn,w:$n,W:Wn,x:l,X:c,y:Gn,Y:Jn,Z:Kn,"%":lt};return t}function Zn(n,t,e){var r=0>n?"-":"",u=(r?-n:n)+"",i=u.length;return r+(e>i?new Array(e-i+1).join(t)+u:u)}function Vn(n){return new RegExp("^(?:"+n.map(oa.requote).join("|")+")","i")}function Xn(n){for(var t=new c,e=-1,r=n.length;++e68?1900:2e3)}function nt(n,t,e){mo.lastIndex=0;var r=mo.exec(t.slice(e,e+2));return r?(n.m=r[0]-1,e+r[0].length):-1}function tt(n,t,e){mo.lastIndex=0;var r=mo.exec(t.slice(e,e+2));return r?(n.d=+r[0],e+r[0].length):-1}function et(n,t,e){mo.lastIndex=0;var r=mo.exec(t.slice(e,e+3));return r?(n.j=+r[0],e+r[0].length):-1}function rt(n,t,e){mo.lastIndex=0;var r=mo.exec(t.slice(e,e+2));return r?(n.H=+r[0],e+r[0].length):-1}function ut(n,t,e){mo.lastIndex=0;var r=mo.exec(t.slice(e,e+2));return r?(n.M=+r[0],e+r[0].length):-1}function it(n,t,e){mo.lastIndex=0;var r=mo.exec(t.slice(e,e+2));return r?(n.S=+r[0],e+r[0].length):-1}function at(n,t,e){mo.lastIndex=0;var r=mo.exec(t.slice(e,e+3));return r?(n.L=+r[0],e+r[0].length):-1}function ot(n){var t=n.getTimezoneOffset(),e=t>0?"-":"+",r=Ma(t)/60|0,u=Ma(t)%60;return e+Zn(r,"0",2)+Zn(u,"0",2)}function lt(n,t,e){yo.lastIndex=0;var r=yo.exec(t.slice(e,e+1));return r?e+r[0].length:-1}function ct(n){for(var t=n.length,e=-1;++e=0?1:-1,o=a*e,l=Math.cos(t),c=Math.sin(t),s=i*c,f=u*l+s*Math.cos(o),h=s*a*Math.sin(o);So.add(Math.atan2(h,f)),r=n,u=l,i=c}var t,e,r,u,i;ko.point=function(a,o){ko.point=n,r=(t=a)*Oa,u=Math.cos(o=(e=o)*Oa/2+ja/4),i=Math.sin(o)},ko.lineEnd=function(){n(t,e)}}function dt(n){var t=n[0],e=n[1],r=Math.cos(e);return[r*Math.cos(t),r*Math.sin(t),Math.sin(e)]}function mt(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]}function yt(n,t){return[n[1]*t[2]-n[2]*t[1],n[2]*t[0]-n[0]*t[2],n[0]*t[1]-n[1]*t[0]]}function Mt(n,t){n[0]+=t[0],n[1]+=t[1],n[2]+=t[2]}function xt(n,t){return[n[0]*t,n[1]*t,n[2]*t]}function bt(n){var t=Math.sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);n[0]/=t,n[1]/=t,n[2]/=t}function _t(n){return[Math.atan2(n[1],n[0]),tn(n[2])]}function wt(n,t){return Ma(n[0]-t[0])o;++o)u.point((e=n[o])[0],e[1]);return void u.lineEnd()}var l=new Tt(e,n,null,!0),c=new Tt(e,null,l,!1);l.o=c,i.push(l),a.push(c),l=new Tt(r,n,null,!1),c=new Tt(r,null,l,!0),l.o=c,i.push(l),a.push(c)}}),a.sort(t),qt(i),qt(a),i.length){for(var o=0,l=e,c=a.length;c>o;++o)a[o].e=l=!l;for(var s,f,h=i[0];;){for(var g=h,p=!0;g.v;)if((g=g.n)===h)return;s=g.z,u.lineStart();do{if(g.v=g.o.v=!0,g.e){if(p)for(var o=0,c=s.length;c>o;++o)u.point((f=s[o])[0],f[1]);else r(g.x,g.n.x,1,u);g=g.n}else{if(p){s=g.p.z;for(var o=s.length-1;o>=0;--o)u.point((f=s[o])[0],f[1])}else r(g.x,g.p.x,-1,u);g=g.p}g=g.o,s=g.z,p=!p}while(!g.v);u.lineEnd()}}}function qt(n){if(t=n.length){for(var t,e,r=0,u=n[0];++r0){for(b||(i.polygonStart(),b=!0),i.lineStart();++a1&&2&t&&e.push(e.pop().concat(e.shift())),g.push(e.filter(Dt))}var g,p,v,d=t(i),m=u.invert(r[0],r[1]),y={point:a,lineStart:l,lineEnd:c,polygonStart:function(){y.point=s,y.lineStart=f,y.lineEnd=h,g=[],p=[]},polygonEnd:function(){y.point=a,y.lineStart=l,y.lineEnd=c,g=oa.merge(g);var n=Ot(m,p);g.length?(b||(i.polygonStart(),b=!0),Lt(g,jt,n,e,i)):n&&(b||(i.polygonStart(),b=!0),i.lineStart(),e(null,null,1,i),i.lineEnd()),b&&(i.polygonEnd(),b=!1),g=p=null},sphere:function(){i.polygonStart(),i.lineStart(),e(null,null,1,i),i.lineEnd(),i.polygonEnd()}},M=Pt(),x=t(M),b=!1;return y}}function Dt(n){return n.length>1}function Pt(){var n,t=[];return{lineStart:function(){t.push(n=[])},point:function(t,e){n.push([t,e])},lineEnd:b,buffer:function(){var e=t;return t=[],n=null,e},rejoin:function(){t.length>1&&t.push(t.pop().concat(t.shift()))}}}function jt(n,t){return((n=n.x)[0]<0?n[1]-Ha-Da:Ha-n[1])-((t=t.x)[0]<0?t[1]-Ha-Da:Ha-t[1])}function Ut(n){var t,e=NaN,r=NaN,u=NaN;return{lineStart:function(){n.lineStart(),t=1},point:function(i,a){var o=i>0?ja:-ja,l=Ma(i-e);Ma(l-ja)0?Ha:-Ha),n.point(u,r),n.lineEnd(),n.lineStart(),n.point(o,r),n.point(i,r),t=0):u!==o&&l>=ja&&(Ma(e-u)Da?Math.atan((Math.sin(t)*(i=Math.cos(r))*Math.sin(e)-Math.sin(r)*(u=Math.cos(t))*Math.sin(n))/(u*i*a)):(t+r)/2}function Ht(n,t,e,r){var u;if(null==n)u=e*Ha,r.point(-ja,u),r.point(0,u),r.point(ja,u),r.point(ja,0),r.point(ja,-u),r.point(0,-u),r.point(-ja,-u),r.point(-ja,0),r.point(-ja,u);else if(Ma(n[0]-t[0])>Da){var i=n[0]o;++o){var c=t[o],s=c.length;if(s)for(var f=c[0],h=f[0],g=f[1]/2+ja/4,p=Math.sin(g),v=Math.cos(g),d=1;;){d===s&&(d=0),n=c[d];var m=n[0],y=n[1]/2+ja/4,M=Math.sin(y),x=Math.cos(y),b=m-h,_=b>=0?1:-1,w=_*b,S=w>ja,k=p*M;if(So.add(Math.atan2(k*_*Math.sin(w),v*x+k*Math.cos(w))),i+=S?b+_*Ua:b,S^h>=e^m>=e){var N=yt(dt(f),dt(n));bt(N);var E=yt(u,N);bt(E);var A=(S^b>=0?-1:1)*tn(E[2]);(r>A||r===A&&(N[0]||N[1]))&&(a+=S^b>=0?1:-1)}if(!d++)break;h=m,p=M,v=x,f=n}}return(-Da>i||Da>i&&0>So)^1&a}function It(n){function t(n,t){return Math.cos(n)*Math.cos(t)>i}function e(n){var e,i,l,c,s;return{lineStart:function(){c=l=!1,s=1},point:function(f,h){var g,p=[f,h],v=t(f,h),d=a?v?0:u(f,h):v?u(f+(0>f?ja:-ja),h):0;if(!e&&(c=l=v)&&n.lineStart(),v!==l&&(g=r(e,p),(wt(e,g)||wt(p,g))&&(p[0]+=Da,p[1]+=Da,v=t(p[0],p[1]))),v!==l)s=0,v?(n.lineStart(),g=r(p,e),n.point(g[0],g[1])):(g=r(e,p),n.point(g[0],g[1]),n.lineEnd()),e=g;else if(o&&e&&a^v){var m;d&i||!(m=r(p,e,!0))||(s=0,a?(n.lineStart(),n.point(m[0][0],m[0][1]),n.point(m[1][0],m[1][1]),n.lineEnd()):(n.point(m[1][0],m[1][1]),n.lineEnd(),n.lineStart(),n.point(m[0][0],m[0][1])))}!v||e&&wt(e,p)||n.point(p[0],p[1]),e=p,l=v,i=d},lineEnd:function(){l&&n.lineEnd(),e=null},clean:function(){return s|(c&&l)<<1}}}function r(n,t,e){var r=dt(n),u=dt(t),a=[1,0,0],o=yt(r,u),l=mt(o,o),c=o[0],s=l-c*c;if(!s)return!e&&n;var f=i*l/s,h=-i*c/s,g=yt(a,o),p=xt(a,f),v=xt(o,h);Mt(p,v);var d=g,m=mt(p,d),y=mt(d,d),M=m*m-y*(mt(p,p)-1);if(!(0>M)){var x=Math.sqrt(M),b=xt(d,(-m-x)/y);if(Mt(b,p),b=_t(b),!e)return b;var _,w=n[0],S=t[0],k=n[1],N=t[1];w>S&&(_=w,w=S,S=_);var E=S-w,A=Ma(E-ja)E;if(!A&&k>N&&(_=k,k=N,N=_),C?A?k+N>0^b[1]<(Ma(b[0]-w)ja^(w<=b[0]&&b[0]<=S)){var z=xt(d,(-m+x)/y);return Mt(z,p),[b,_t(z)]}}}function u(t,e){var r=a?n:ja-n,u=0;return-r>t?u|=1:t>r&&(u|=2),-r>e?u|=4:e>r&&(u|=8),u}var i=Math.cos(n),a=i>0,o=Ma(i)>Da,l=ve(n,6*Oa);return Rt(t,e,l,a?[0,-n]:[-ja,n-ja])}function Yt(n,t,e,r){return function(u){var i,a=u.a,o=u.b,l=a.x,c=a.y,s=o.x,f=o.y,h=0,g=1,p=s-l,v=f-c;if(i=n-l,p||!(i>0)){if(i/=p,0>p){if(h>i)return;g>i&&(g=i)}else if(p>0){if(i>g)return;i>h&&(h=i)}if(i=e-l,p||!(0>i)){if(i/=p,0>p){if(i>g)return;i>h&&(h=i)}else if(p>0){if(h>i)return;g>i&&(g=i)}if(i=t-c,v||!(i>0)){if(i/=v,0>v){if(h>i)return;g>i&&(g=i)}else if(v>0){if(i>g)return;i>h&&(h=i)}if(i=r-c,v||!(0>i)){if(i/=v,0>v){if(i>g)return;i>h&&(h=i)}else if(v>0){if(h>i)return;g>i&&(g=i)}return h>0&&(u.a={x:l+h*p,y:c+h*v}),1>g&&(u.b={x:l+g*p,y:c+g*v}),u}}}}}}function Zt(n,t,e,r){function u(r,u){return Ma(r[0]-n)0?0:3:Ma(r[0]-e)0?2:1:Ma(r[1]-t)0?1:0:u>0?3:2}function i(n,t){return a(n.x,t.x)}function a(n,t){var e=u(n,1),r=u(t,1);return e!==r?e-r:0===e?t[1]-n[1]:1===e?n[0]-t[0]:2===e?n[1]-t[1]:t[0]-n[0]}return function(o){function l(n){for(var t=0,e=d.length,r=n[1],u=0;e>u;++u)for(var i,a=1,o=d[u],l=o.length,c=o[0];l>a;++a)i=o[a],c[1]<=r?i[1]>r&&Q(c,i,n)>0&&++t:i[1]<=r&&Q(c,i,n)<0&&--t,c=i;return 0!==t}function c(i,o,l,c){var s=0,f=0;if(null==i||(s=u(i,l))!==(f=u(o,l))||a(i,o)<0^l>0){do c.point(0===s||3===s?n:e,s>1?r:t);while((s=(s+l+4)%4)!==f)}else c.point(o[0],o[1])}function s(u,i){return u>=n&&e>=u&&i>=t&&r>=i}function f(n,t){s(n,t)&&o.point(n,t)}function h(){C.point=p,d&&d.push(m=[]),S=!0,w=!1,b=_=NaN}function g(){v&&(p(y,M),x&&w&&E.rejoin(),v.push(E.buffer())),C.point=f,w&&o.lineEnd()}function p(n,t){n=Math.max(-Fo,Math.min(Fo,n)),t=Math.max(-Fo,Math.min(Fo,t));var e=s(n,t);if(d&&m.push([n,t]),S)y=n,M=t,x=e,S=!1,e&&(o.lineStart(),o.point(n,t));else if(e&&w)o.point(n,t);else{var r={a:{x:b,y:_},b:{x:n,y:t}};A(r)?(w||(o.lineStart(),o.point(r.a.x,r.a.y)),o.point(r.b.x,r.b.y),e||o.lineEnd(),k=!1):e&&(o.lineStart(),o.point(n,t),k=!1)}b=n,_=t,w=e}var v,d,m,y,M,x,b,_,w,S,k,N=o,E=Pt(),A=Yt(n,t,e,r),C={point:f,lineStart:h,lineEnd:g,polygonStart:function(){o=E,v=[],d=[],k=!0},polygonEnd:function(){o=N,v=oa.merge(v);var t=l([n,r]),e=k&&t,u=v.length;(e||u)&&(o.polygonStart(),e&&(o.lineStart(),c(null,null,1,o),o.lineEnd()),u&&Lt(v,i,t,c,o),o.polygonEnd()),v=d=m=null}};return C}}function Vt(n){var t=0,e=ja/3,r=oe(n),u=r(t,e);return u.parallels=function(n){return arguments.length?r(t=n[0]*ja/180,e=n[1]*ja/180):[t/ja*180,e/ja*180]},u}function Xt(n,t){function e(n,t){var e=Math.sqrt(i-2*u*Math.sin(t))/u;return[e*Math.sin(n*=u),a-e*Math.cos(n)]}var r=Math.sin(n),u=(r+Math.sin(t))/2,i=1+r*(2*u-r),a=Math.sqrt(i)/u;return e.invert=function(n,t){var e=a-t;return[Math.atan2(n,e)/u,tn((i-(n*n+e*e)*u*u)/(2*u))]},e}function $t(){function n(n,t){Oo+=u*n-r*t,r=n,u=t}var t,e,r,u;Xo.point=function(i,a){Xo.point=n,t=r=i,e=u=a},Xo.lineEnd=function(){n(t,e)}}function Bt(n,t){Io>n&&(Io=n),n>Zo&&(Zo=n),Yo>t&&(Yo=t),t>Vo&&(Vo=t)}function Wt(){function n(n,t){a.push("M",n,",",t,i)}function t(n,t){a.push("M",n,",",t),o.point=e}function e(n,t){a.push("L",n,",",t)}function r(){o.point=n}function u(){a.push("Z")}var i=Jt(4.5),a=[],o={point:n,lineStart:function(){o.point=t},lineEnd:r,polygonStart:function(){o.lineEnd=u},polygonEnd:function(){o.lineEnd=r,o.point=n},pointRadius:function(n){return i=Jt(n),o},result:function(){if(a.length){var n=a.join("");return a=[],n}}};return o}function Jt(n){return"m0,"+n+"a"+n+","+n+" 0 1,1 0,"+-2*n+"a"+n+","+n+" 0 1,1 0,"+2*n+"z"}function Gt(n,t){Ao+=n,Co+=t,++zo}function Kt(){function n(n,r){var u=n-t,i=r-e,a=Math.sqrt(u*u+i*i);Lo+=a*(t+n)/2,qo+=a*(e+r)/2,To+=a,Gt(t=n,e=r)}var t,e;Bo.point=function(r,u){Bo.point=n,Gt(t=r,e=u)}}function Qt(){Bo.point=Gt}function ne(){function n(n,t){var e=n-r,i=t-u,a=Math.sqrt(e*e+i*i);Lo+=a*(r+n)/2,qo+=a*(u+t)/2,To+=a,a=u*n-r*t,Ro+=a*(r+n),Do+=a*(u+t),Po+=3*a,Gt(r=n,u=t)}var t,e,r,u;Bo.point=function(i,a){Bo.point=n,Gt(t=r=i,e=u=a)},Bo.lineEnd=function(){n(t,e)}}function te(n){function t(t,e){n.moveTo(t+a,e),n.arc(t,e,a,0,Ua)}function e(t,e){n.moveTo(t,e),o.point=r}function r(t,e){n.lineTo(t,e)}function u(){o.point=t}function i(){n.closePath()}var a=4.5,o={point:t,lineStart:function(){o.point=e},lineEnd:u,polygonStart:function(){o.lineEnd=i},polygonEnd:function(){o.lineEnd=u,o.point=t},pointRadius:function(n){return a=n,o},result:b};return o}function ee(n){function t(n){return(o?r:e)(n)}function e(t){return ie(t,function(e,r){e=n(e,r),t.point(e[0],e[1])})}function r(t){function e(e,r){e=n(e,r),t.point(e[0],e[1])}function r(){M=NaN,S.point=i,t.lineStart()}function i(e,r){var i=dt([e,r]),a=n(e,r);u(M,x,y,b,_,w,M=a[0],x=a[1],y=e,b=i[0],_=i[1],w=i[2],o,t),t.point(M,x)}function a(){S.point=e,t.lineEnd()}function l(){r(),S.point=c,S.lineEnd=s}function c(n,t){ +i(f=n,h=t),g=M,p=x,v=b,d=_,m=w,S.point=i}function s(){u(M,x,y,b,_,w,g,p,f,v,d,m,o,t),S.lineEnd=a,a()}var f,h,g,p,v,d,m,y,M,x,b,_,w,S={point:e,lineStart:r,lineEnd:a,polygonStart:function(){t.polygonStart(),S.lineStart=l},polygonEnd:function(){t.polygonEnd(),S.lineStart=r}};return S}function u(t,e,r,o,l,c,s,f,h,g,p,v,d,m){var y=s-t,M=f-e,x=y*y+M*M;if(x>4*i&&d--){var b=o+g,_=l+p,w=c+v,S=Math.sqrt(b*b+_*_+w*w),k=Math.asin(w/=S),N=Ma(Ma(w)-1)i||Ma((y*z+M*L)/x-.5)>.3||a>o*g+l*p+c*v)&&(u(t,e,r,o,l,c,A,C,N,b/=S,_/=S,w,d,m),m.point(A,C),u(A,C,N,b,_,w,s,f,h,g,p,v,d,m))}}var i=.5,a=Math.cos(30*Oa),o=16;return t.precision=function(n){return arguments.length?(o=(i=n*n)>0&&16,t):Math.sqrt(i)},t}function re(n){var t=ee(function(t,e){return n([t*Ia,e*Ia])});return function(n){return le(t(n))}}function ue(n){this.stream=n}function ie(n,t){return{point:t,sphere:function(){n.sphere()},lineStart:function(){n.lineStart()},lineEnd:function(){n.lineEnd()},polygonStart:function(){n.polygonStart()},polygonEnd:function(){n.polygonEnd()}}}function ae(n){return oe(function(){return n})()}function oe(n){function t(n){return n=o(n[0]*Oa,n[1]*Oa),[n[0]*h+l,c-n[1]*h]}function e(n){return n=o.invert((n[0]-l)/h,(c-n[1])/h),n&&[n[0]*Ia,n[1]*Ia]}function r(){o=Ct(a=fe(m,M,x),i);var n=i(v,d);return l=g-n[0]*h,c=p+n[1]*h,u()}function u(){return s&&(s.valid=!1,s=null),t}var i,a,o,l,c,s,f=ee(function(n,t){return n=i(n,t),[n[0]*h+l,c-n[1]*h]}),h=150,g=480,p=250,v=0,d=0,m=0,M=0,x=0,b=Uo,_=y,w=null,S=null;return t.stream=function(n){return s&&(s.valid=!1),s=le(b(a,f(_(n)))),s.valid=!0,s},t.clipAngle=function(n){return arguments.length?(b=null==n?(w=n,Uo):It((w=+n)*Oa),u()):w},t.clipExtent=function(n){return arguments.length?(S=n,_=n?Zt(n[0][0],n[0][1],n[1][0],n[1][1]):y,u()):S},t.scale=function(n){return arguments.length?(h=+n,r()):h},t.translate=function(n){return arguments.length?(g=+n[0],p=+n[1],r()):[g,p]},t.center=function(n){return arguments.length?(v=n[0]%360*Oa,d=n[1]%360*Oa,r()):[v*Ia,d*Ia]},t.rotate=function(n){return arguments.length?(m=n[0]%360*Oa,M=n[1]%360*Oa,x=n.length>2?n[2]%360*Oa:0,r()):[m*Ia,M*Ia,x*Ia]},oa.rebind(t,f,"precision"),function(){return i=n.apply(this,arguments),t.invert=i.invert&&e,r()}}function le(n){return ie(n,function(t,e){n.point(t*Oa,e*Oa)})}function ce(n,t){return[n,t]}function se(n,t){return[n>ja?n-Ua:-ja>n?n+Ua:n,t]}function fe(n,t,e){return n?t||e?Ct(ge(n),pe(t,e)):ge(n):t||e?pe(t,e):se}function he(n){return function(t,e){return t+=n,[t>ja?t-Ua:-ja>t?t+Ua:t,e]}}function ge(n){var t=he(n);return t.invert=he(-n),t}function pe(n,t){function e(n,t){var e=Math.cos(t),o=Math.cos(n)*e,l=Math.sin(n)*e,c=Math.sin(t),s=c*r+o*u;return[Math.atan2(l*i-s*a,o*r-c*u),tn(s*i+l*a)]}var r=Math.cos(n),u=Math.sin(n),i=Math.cos(t),a=Math.sin(t);return e.invert=function(n,t){var e=Math.cos(t),o=Math.cos(n)*e,l=Math.sin(n)*e,c=Math.sin(t),s=c*i-l*a;return[Math.atan2(l*i+c*a,o*r+s*u),tn(s*r-o*u)]},e}function ve(n,t){var e=Math.cos(n),r=Math.sin(n);return function(u,i,a,o){var l=a*t;null!=u?(u=de(e,u),i=de(e,i),(a>0?i>u:u>i)&&(u+=a*Ua)):(u=n+a*Ua,i=n-.5*l);for(var c,s=u;a>0?s>i:i>s;s-=l)o.point((c=_t([e,-r*Math.cos(s),-r*Math.sin(s)]))[0],c[1])}}function de(n,t){var e=dt(t);e[0]-=n,bt(e);var r=nn(-e[1]);return((-e[2]<0?-r:r)+2*Math.PI-Da)%(2*Math.PI)}function me(n,t,e){var r=oa.range(n,t-Da,e).concat(t);return function(n){return r.map(function(t){return[n,t]})}}function ye(n,t,e){var r=oa.range(n,t-Da,e).concat(t);return function(n){return r.map(function(t){return[t,n]})}}function Me(n){return n.source}function xe(n){return n.target}function be(n,t,e,r){var u=Math.cos(t),i=Math.sin(t),a=Math.cos(r),o=Math.sin(r),l=u*Math.cos(n),c=u*Math.sin(n),s=a*Math.cos(e),f=a*Math.sin(e),h=2*Math.asin(Math.sqrt(an(r-t)+u*a*an(e-n))),g=1/Math.sin(h),p=h?function(n){var t=Math.sin(n*=h)*g,e=Math.sin(h-n)*g,r=e*l+t*s,u=e*c+t*f,a=e*i+t*o;return[Math.atan2(u,r)*Ia,Math.atan2(a,Math.sqrt(r*r+u*u))*Ia]}:function(){return[n*Ia,t*Ia]};return p.distance=h,p}function _e(){function n(n,u){var i=Math.sin(u*=Oa),a=Math.cos(u),o=Ma((n*=Oa)-t),l=Math.cos(o);Wo+=Math.atan2(Math.sqrt((o=a*Math.sin(o))*o+(o=r*i-e*a*l)*o),e*i+r*a*l),t=n,e=i,r=a}var t,e,r;Jo.point=function(u,i){t=u*Oa,e=Math.sin(i*=Oa),r=Math.cos(i),Jo.point=n},Jo.lineEnd=function(){Jo.point=Jo.lineEnd=b}}function we(n,t){function e(t,e){var r=Math.cos(t),u=Math.cos(e),i=n(r*u);return[i*u*Math.sin(t),i*Math.sin(e)]}return e.invert=function(n,e){var r=Math.sqrt(n*n+e*e),u=t(r),i=Math.sin(u),a=Math.cos(u);return[Math.atan2(n*i,r*a),Math.asin(r&&e*i/r)]},e}function Se(n,t){function e(n,t){a>0?-Ha+Da>t&&(t=-Ha+Da):t>Ha-Da&&(t=Ha-Da);var e=a/Math.pow(u(t),i);return[e*Math.sin(i*n),a-e*Math.cos(i*n)]}var r=Math.cos(n),u=function(n){return Math.tan(ja/4+n/2)},i=n===t?Math.sin(n):Math.log(r/Math.cos(t))/Math.log(u(t)/u(n)),a=r*Math.pow(u(n),i)/i;return i?(e.invert=function(n,t){var e=a-t,r=K(i)*Math.sqrt(n*n+e*e);return[Math.atan2(n,e)/i,2*Math.atan(Math.pow(a/r,1/i))-Ha]},e):Ne}function ke(n,t){function e(n,t){var e=i-t;return[e*Math.sin(u*n),i-e*Math.cos(u*n)]}var r=Math.cos(n),u=n===t?Math.sin(n):(r-Math.cos(t))/(t-n),i=r/u+n;return Ma(u)u;u++){for(;r>1&&Q(n[e[r-2]],n[e[r-1]],n[u])<=0;)--r;e[r++]=u}return e.slice(0,r)}function qe(n,t){return n[0]-t[0]||n[1]-t[1]}function Te(n,t,e){return(e[0]-t[0])*(n[1]-t[1])<(e[1]-t[1])*(n[0]-t[0])}function Re(n,t,e,r){var u=n[0],i=e[0],a=t[0]-u,o=r[0]-i,l=n[1],c=e[1],s=t[1]-l,f=r[1]-c,h=(o*(l-c)-f*(u-i))/(f*a-o*s);return[u+h*a,l+h*s]}function De(n){var t=n[0],e=n[n.length-1];return!(t[0]-e[0]||t[1]-e[1])}function Pe(){rr(this),this.edge=this.site=this.circle=null}function je(n){var t=ll.pop()||new Pe;return t.site=n,t}function Ue(n){Be(n),il.remove(n),ll.push(n),rr(n)}function Fe(n){var t=n.circle,e=t.x,r=t.cy,u={x:e,y:r},i=n.P,a=n.N,o=[n];Ue(n);for(var l=i;l.circle&&Ma(e-l.circle.x)s;++s)c=o[s],l=o[s-1],nr(c.edge,l.site,c.site,u);l=o[0],c=o[f-1],c.edge=Ke(l.site,c.site,null,u),$e(l),$e(c)}function He(n){for(var t,e,r,u,i=n.x,a=n.y,o=il._;o;)if(r=Oe(o,a)-i,r>Da)o=o.L;else{if(u=i-Ie(o,a),!(u>Da)){r>-Da?(t=o.P,e=o):u>-Da?(t=o,e=o.N):t=e=o;break}if(!o.R){t=o;break}o=o.R}var l=je(n);if(il.insert(t,l),t||e){if(t===e)return Be(t),e=je(t.site),il.insert(l,e),l.edge=e.edge=Ke(t.site,l.site),$e(t),void $e(e);if(!e)return void(l.edge=Ke(t.site,l.site));Be(t),Be(e);var c=t.site,s=c.x,f=c.y,h=n.x-s,g=n.y-f,p=e.site,v=p.x-s,d=p.y-f,m=2*(h*d-g*v),y=h*h+g*g,M=v*v+d*d,x={x:(d*y-g*M)/m+s,y:(h*M-v*y)/m+f};nr(e.edge,c,p,x),l.edge=Ke(c,n,null,x),e.edge=Ke(n,p,null,x),$e(t),$e(e)}}function Oe(n,t){var e=n.site,r=e.x,u=e.y,i=u-t;if(!i)return r;var a=n.P;if(!a)return-(1/0);e=a.site;var o=e.x,l=e.y,c=l-t;if(!c)return o;var s=o-r,f=1/i-1/c,h=s/c;return f?(-h+Math.sqrt(h*h-2*f*(s*s/(-2*c)-l+c/2+u-i/2)))/f+r:(r+o)/2}function Ie(n,t){var e=n.N;if(e)return Oe(e,t);var r=n.site;return r.y===t?r.x:1/0}function Ye(n){this.site=n,this.edges=[]}function Ze(n){for(var t,e,r,u,i,a,o,l,c,s,f=n[0][0],h=n[1][0],g=n[0][1],p=n[1][1],v=ul,d=v.length;d--;)if(i=v[d],i&&i.prepare())for(o=i.edges,l=o.length,a=0;l>a;)s=o[a].end(),r=s.x,u=s.y,c=o[++a%l].start(),t=c.x,e=c.y,(Ma(r-t)>Da||Ma(u-e)>Da)&&(o.splice(a,0,new tr(Qe(i.site,s,Ma(r-f)Da?{x:f,y:Ma(t-f)Da?{x:Ma(e-p)Da?{x:h,y:Ma(t-h)Da?{x:Ma(e-g)=-Pa)){var g=l*l+c*c,p=s*s+f*f,v=(f*g-c*p)/h,d=(l*p-s*g)/h,f=d+o,m=cl.pop()||new Xe;m.arc=n,m.site=u,m.x=v+a,m.y=f+Math.sqrt(v*v+d*d),m.cy=f,n.circle=m;for(var y=null,M=ol._;M;)if(m.yd||d>=o)return;if(h>p){if(i){if(i.y>=c)return}else i={x:d,y:l};e={x:d,y:c}}else{if(i){if(i.yr||r>1)if(h>p){if(i){if(i.y>=c)return}else i={x:(l-u)/r,y:l};e={x:(c-u)/r,y:c}}else{if(i){if(i.yg){if(i){if(i.x>=o)return}else i={x:a,y:r*a+u};e={x:o,y:r*o+u}}else{if(i){if(i.xi||f>a||r>h||u>g)){if(p=n.point){var p,v=t-n.x,d=e-n.y,m=v*v+d*d;if(l>m){var y=Math.sqrt(l=m);r=t-y,u=e-y,i=t+y,a=e+y,o=p}}for(var M=n.nodes,x=.5*(s+h),b=.5*(f+g),_=t>=x,w=e>=b,S=w<<1|_,k=S+4;k>S;++S)if(n=M[3&S])switch(3&S){case 0:c(n,s,f,x,b);break;case 1:c(n,x,f,h,b);break;case 2:c(n,s,b,x,g);break;case 3:c(n,x,b,h,g)}}}(n,r,u,i,a),o}function vr(n,t){n=oa.rgb(n),t=oa.rgb(t);var e=n.r,r=n.g,u=n.b,i=t.r-e,a=t.g-r,o=t.b-u;return function(n){return"#"+bn(Math.round(e+i*n))+bn(Math.round(r+a*n))+bn(Math.round(u+o*n))}}function dr(n,t){var e,r={},u={};for(e in n)e in t?r[e]=Mr(n[e],t[e]):u[e]=n[e];for(e in t)e in n||(u[e]=t[e]);return function(n){for(e in r)u[e]=r[e](n);return u}}function mr(n,t){return n=+n,t=+t,function(e){return n*(1-e)+t*e}}function yr(n,t){var e,r,u,i=fl.lastIndex=hl.lastIndex=0,a=-1,o=[],l=[];for(n+="",t+="";(e=fl.exec(n))&&(r=hl.exec(t));)(u=r.index)>i&&(u=t.slice(i,u),o[a]?o[a]+=u:o[++a]=u),(e=e[0])===(r=r[0])?o[a]?o[a]+=r:o[++a]=r:(o[++a]=null,l.push({i:a,x:mr(e,r)})),i=hl.lastIndex;return ir;++r)o[(e=l[r]).i]=e.x(n);return o.join("")})}function Mr(n,t){for(var e,r=oa.interpolators.length;--r>=0&&!(e=oa.interpolators[r](n,t)););return e}function xr(n,t){var e,r=[],u=[],i=n.length,a=t.length,o=Math.min(n.length,t.length);for(e=0;o>e;++e)r.push(Mr(n[e],t[e]));for(;i>e;++e)u[e]=n[e];for(;a>e;++e)u[e]=t[e];return function(n){for(e=0;o>e;++e)u[e]=r[e](n);return u}}function br(n){return function(t){return 0>=t?0:t>=1?1:n(t)}}function _r(n){return function(t){return 1-n(1-t)}}function wr(n){return function(t){return.5*(.5>t?n(2*t):2-n(2-2*t))}}function Sr(n){return n*n}function kr(n){return n*n*n}function Nr(n){if(0>=n)return 0;if(n>=1)return 1;var t=n*n,e=t*n;return 4*(.5>n?e:3*(n-t)+e-.75)}function Er(n){return function(t){return Math.pow(t,n)}}function Ar(n){return 1-Math.cos(n*Ha)}function Cr(n){return Math.pow(2,10*(n-1))}function zr(n){return 1-Math.sqrt(1-n*n)}function Lr(n,t){var e;return arguments.length<2&&(t=.45),arguments.length?e=t/Ua*Math.asin(1/n):(n=1,e=t/4),function(r){return 1+n*Math.pow(2,-10*r)*Math.sin((r-e)*Ua/t)}}function qr(n){return n||(n=1.70158),function(t){return t*t*((n+1)*t-n)}}function Tr(n){return 1/2.75>n?7.5625*n*n:2/2.75>n?7.5625*(n-=1.5/2.75)*n+.75:2.5/2.75>n?7.5625*(n-=2.25/2.75)*n+.9375:7.5625*(n-=2.625/2.75)*n+.984375}function Rr(n,t){n=oa.hcl(n),t=oa.hcl(t);var e=n.h,r=n.c,u=n.l,i=t.h-e,a=t.c-r,o=t.l-u;return isNaN(a)&&(a=0,r=isNaN(r)?t.c:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return fn(e+i*n,r+a*n,u+o*n)+""}}function Dr(n,t){n=oa.hsl(n),t=oa.hsl(t);var e=n.h,r=n.s,u=n.l,i=t.h-e,a=t.s-r,o=t.l-u;return isNaN(a)&&(a=0,r=isNaN(r)?t.s:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return cn(e+i*n,r+a*n,u+o*n)+""}}function Pr(n,t){n=oa.lab(n),t=oa.lab(t);var e=n.l,r=n.a,u=n.b,i=t.l-e,a=t.a-r,o=t.b-u;return function(n){return gn(e+i*n,r+a*n,u+o*n)+""}}function jr(n,t){return t-=n,function(e){return Math.round(n+t*e)}}function Ur(n){var t=[n.a,n.b],e=[n.c,n.d],r=Hr(t),u=Fr(t,e),i=Hr(Or(e,t,-u))||0;t[0]*e[1]180?t+=360:t-n>180&&(n+=360),r.push({i:e.push(Ir(e)+"rotate(",null,")")-2,x:mr(n,t)})):t&&e.push(Ir(e)+"rotate("+t+")")}function Vr(n,t,e,r){n!==t?r.push({i:e.push(Ir(e)+"skewX(",null,")")-2,x:mr(n,t)}):t&&e.push(Ir(e)+"skewX("+t+")")}function Xr(n,t,e,r){if(n[0]!==t[0]||n[1]!==t[1]){var u=e.push(Ir(e)+"scale(",null,",",null,")");r.push({i:u-4,x:mr(n[0],t[0])},{i:u-2,x:mr(n[1],t[1])})}else(1!==t[0]||1!==t[1])&&e.push(Ir(e)+"scale("+t+")")}function $r(n,t){var e=[],r=[];return n=oa.transform(n),t=oa.transform(t),Yr(n.translate,t.translate,e,r),Zr(n.rotate,t.rotate,e,r),Vr(n.skew,t.skew,e,r),Xr(n.scale,t.scale,e,r),n=t=null,function(n){for(var t,u=-1,i=r.length;++u=0;)e.push(u[r])}function au(n,t){for(var e=[n],r=[];null!=(n=e.pop());)if(r.push(n),(i=n.children)&&(u=i.length))for(var u,i,a=-1;++ae;++e)(t=n[e][1])>u&&(r=e,u=t);return r}function mu(n){return n.reduce(yu,0)}function yu(n,t){return n+t[1]}function Mu(n,t){return xu(n,Math.ceil(Math.log(t.length)/Math.LN2+1))}function xu(n,t){for(var e=-1,r=+n[0],u=(n[1]-r)/t,i=[];++e<=t;)i[e]=u*e+r;return i}function bu(n){return[oa.min(n),oa.max(n)]}function _u(n,t){return n.value-t.value}function wu(n,t){var e=n._pack_next;n._pack_next=t,t._pack_prev=n,t._pack_next=e,e._pack_prev=t}function Su(n,t){n._pack_next=t,t._pack_prev=n}function ku(n,t){var e=t.x-n.x,r=t.y-n.y,u=n.r+t.r;return.999*u*u>e*e+r*r}function Nu(n){function t(n){s=Math.min(n.x-n.r,s),f=Math.max(n.x+n.r,f),h=Math.min(n.y-n.r,h),g=Math.max(n.y+n.r,g)}if((e=n.children)&&(c=e.length)){var e,r,u,i,a,o,l,c,s=1/0,f=-(1/0),h=1/0,g=-(1/0);if(e.forEach(Eu),r=e[0],r.x=-r.r,r.y=0,t(r),c>1&&(u=e[1],u.x=u.r,u.y=0,t(u),c>2))for(i=e[2],zu(r,u,i),t(i),wu(r,i),r._pack_prev=i,wu(i,u),u=r._pack_next,a=3;c>a;a++){zu(r,u,i=e[a]);var p=0,v=1,d=1;for(o=u._pack_next;o!==u;o=o._pack_next,v++)if(ku(o,i)){p=1;break}if(1==p)for(l=r._pack_prev;l!==o._pack_prev&&!ku(l,i);l=l._pack_prev,d++);p?(d>v||v==d&&u.ra;a++)i=e[a],i.x-=m,i.y-=y,M=Math.max(M,i.r+Math.sqrt(i.x*i.x+i.y*i.y));n.r=M,e.forEach(Au)}}function Eu(n){n._pack_next=n._pack_prev=n}function Au(n){delete n._pack_next,delete n._pack_prev}function Cu(n,t,e,r){var u=n.children;if(n.x=t+=r*n.x,n.y=e+=r*n.y,n.r*=r,u)for(var i=-1,a=u.length;++i=0;)t=u[i],t.z+=e,t.m+=e,e+=t.s+(r+=t.c)}function Pu(n,t,e){return n.a.parent===t.parent?n.a:e}function ju(n){return 1+oa.max(n,function(n){return n.y})}function Uu(n){return n.reduce(function(n,t){return n+t.x},0)/n.length}function Fu(n){var t=n.children;return t&&t.length?Fu(t[0]):n}function Hu(n){var t,e=n.children;return e&&(t=e.length)?Hu(e[t-1]):n}function Ou(n){return{x:n.x,y:n.y,dx:n.dx,dy:n.dy}}function Iu(n,t){var e=n.x+t[3],r=n.y+t[0],u=n.dx-t[1]-t[3],i=n.dy-t[0]-t[2];return 0>u&&(e+=u/2,u=0),0>i&&(r+=i/2,i=0),{x:e,y:r,dx:u,dy:i}}function Yu(n){var t=n[0],e=n[n.length-1];return e>t?[t,e]:[e,t]}function Zu(n){return n.rangeExtent?n.rangeExtent():Yu(n.range())}function Vu(n,t,e,r){var u=e(n[0],n[1]),i=r(t[0],t[1]);return function(n){return i(u(n))}}function Xu(n,t){var e,r=0,u=n.length-1,i=n[r],a=n[u];return i>a&&(e=r,r=u,u=e,e=i,i=a,a=e),n[r]=t.floor(i),n[u]=t.ceil(a),n}function $u(n){return n?{floor:function(t){return Math.floor(t/n)*n},ceil:function(t){return Math.ceil(t/n)*n}}:wl}function Bu(n,t,e,r){var u=[],i=[],a=0,o=Math.min(n.length,t.length)-1;for(n[o]2?Bu:Vu,l=r?Wr:Br;return a=u(n,t,l,e),o=u(t,n,l,Mr),i}function i(n){return a(n)}var a,o;return i.invert=function(n){return o(n)},i.domain=function(t){return arguments.length?(n=t.map(Number),u()):n},i.range=function(n){return arguments.length?(t=n,u()):t},i.rangeRound=function(n){return i.range(n).interpolate(jr)},i.clamp=function(n){return arguments.length?(r=n,u()):r},i.interpolate=function(n){return arguments.length?(e=n,u()):e},i.ticks=function(t){return Qu(n,t)},i.tickFormat=function(t,e){return ni(n,t,e)},i.nice=function(t){return Gu(n,t),u()},i.copy=function(){return Wu(n,t,e,r)},u()}function Ju(n,t){return oa.rebind(n,t,"range","rangeRound","interpolate","clamp")}function Gu(n,t){return Xu(n,$u(Ku(n,t)[2]))}function Ku(n,t){null==t&&(t=10);var e=Yu(n),r=e[1]-e[0],u=Math.pow(10,Math.floor(Math.log(r/t)/Math.LN10)),i=t/r*u;return.15>=i?u*=10:.35>=i?u*=5:.75>=i&&(u*=2),e[0]=Math.ceil(e[0]/u)*u,e[1]=Math.floor(e[1]/u)*u+.5*u,e[2]=u,e}function Qu(n,t){return oa.range.apply(oa,Ku(n,t))}function ni(n,t,e){var r=Ku(n,t);if(e){var u=so.exec(e);if(u.shift(),"s"===u[8]){var i=oa.formatPrefix(Math.max(Ma(r[0]),Ma(r[1])));return u[7]||(u[7]="."+ti(i.scale(r[2]))),u[8]="f",e=oa.format(u.join("")),function(n){return e(i.scale(n))+i.symbol}}u[7]||(u[7]="."+ei(u[8],r)),e=u.join("")}else e=",."+ti(r[2])+"f";return oa.format(e)}function ti(n){return-Math.floor(Math.log(n)/Math.LN10+.01)}function ei(n,t){var e=ti(t[2]);return n in Sl?Math.abs(e-ti(Math.max(Ma(t[0]),Ma(t[1]))))+ +("e"!==n):e-2*("%"===n)}function ri(n,t,e,r){function u(n){return(e?Math.log(0>n?0:n):-Math.log(n>0?0:-n))/Math.log(t)}function i(n){return e?Math.pow(t,n):-Math.pow(t,-n)}function a(t){return n(u(t))}return a.invert=function(t){return i(n.invert(t))},a.domain=function(t){return arguments.length?(e=t[0]>=0,n.domain((r=t.map(Number)).map(u)),a):r},a.base=function(e){return arguments.length?(t=+e,n.domain(r.map(u)),a):t},a.nice=function(){var t=Xu(r.map(u),e?Math:Nl);return n.domain(t),r=t.map(i),a},a.ticks=function(){var n=Yu(r),a=[],o=n[0],l=n[1],c=Math.floor(u(o)),s=Math.ceil(u(l)),f=t%1?2:t;if(isFinite(s-c)){if(e){for(;s>c;c++)for(var h=1;f>h;h++)a.push(i(c)*h);a.push(i(c))}else for(a.push(i(c));c++0;h--)a.push(i(c)*h);for(c=0;a[c]l;s--);a=a.slice(c,s)}return a},a.tickFormat=function(n,t){if(!arguments.length)return kl;arguments.length<2?t=kl:"function"!=typeof t&&(t=oa.format(t));var r,o=Math.max(.1,n/a.ticks().length),l=e?(r=1e-12,Math.ceil):(r=-1e-12,Math.floor);return function(n){return n/i(l(u(n)+r))<=o?t(n):""}},a.copy=function(){return ri(n.copy(),t,e,r)},Ju(a,n)}function ui(n,t,e){function r(t){return n(u(t))}var u=ii(t),i=ii(1/t);return r.invert=function(t){return i(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain((e=t.map(Number)).map(u)),r):e},r.ticks=function(n){return Qu(e,n)},r.tickFormat=function(n,t){return ni(e,n,t)},r.nice=function(n){return r.domain(Gu(e,n))},r.exponent=function(a){return arguments.length?(u=ii(t=a),i=ii(1/t),n.domain(e.map(u)),r):t},r.copy=function(){return ui(n.copy(),t,e)},Ju(r,n)}function ii(n){return function(t){return 0>t?-Math.pow(-t,n):Math.pow(t,n)}}function ai(n,t){function e(e){return i[((u.get(e)||("range"===t.t?u.set(e,n.push(e)):NaN))-1)%i.length]}function r(t,e){return oa.range(n.length).map(function(n){return t+e*n})}var u,i,a;return e.domain=function(r){if(!arguments.length)return n;n=[],u=new c;for(var i,a=-1,o=r.length;++ae?[NaN,NaN]:[e>0?o[e-1]:n[0],et?NaN:t/i+n,[t,t+1/i]},r.copy=function(){return li(n,t,e)},u()}function ci(n,t){function e(e){return e>=e?t[oa.bisect(n,e)]:void 0}return e.domain=function(t){return arguments.length?(n=t,e):n},e.range=function(n){return arguments.length?(t=n,e):t},e.invertExtent=function(e){return e=t.indexOf(e),[n[e-1],n[e]]},e.copy=function(){return ci(n,t)},e}function si(n){function t(n){return+n}return t.invert=t,t.domain=t.range=function(e){return arguments.length?(n=e.map(t),t):n},t.ticks=function(t){return Qu(n,t)},t.tickFormat=function(t,e){return ni(n,t,e)},t.copy=function(){return si(n)},t}function fi(){return 0}function hi(n){return n.innerRadius}function gi(n){return n.outerRadius}function pi(n){return n.startAngle}function vi(n){return n.endAngle}function di(n){return n&&n.padAngle}function mi(n,t,e,r){return(n-e)*t-(t-r)*n>0?0:1}function yi(n,t,e,r,u){var i=n[0]-t[0],a=n[1]-t[1],o=(u?r:-r)/Math.sqrt(i*i+a*a),l=o*a,c=-o*i,s=n[0]+l,f=n[1]+c,h=t[0]+l,g=t[1]+c,p=(s+h)/2,v=(f+g)/2,d=h-s,m=g-f,y=d*d+m*m,M=e-r,x=s*g-h*f,b=(0>m?-1:1)*Math.sqrt(Math.max(0,M*M*y-x*x)),_=(x*m-d*b)/y,w=(-x*d-m*b)/y,S=(x*m+d*b)/y,k=(-x*d+m*b)/y,N=_-p,E=w-v,A=S-p,C=k-v;return N*N+E*E>A*A+C*C&&(_=S,w=k),[[_-l,w-c],[_*e/M,w*e/M]]}function Mi(n){function t(t){function a(){c.push("M",i(n(s),o))}for(var l,c=[],s=[],f=-1,h=t.length,g=En(e),p=En(r);++f1?n.join("L"):n+"Z"}function bi(n){return n.join("L")+"Z"}function _i(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t1&&u.push("H",r[0]),u.join("")}function wi(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t1){o=t[1],i=n[l],l++,r+="C"+(u[0]+a[0])+","+(u[1]+a[1])+","+(i[0]-o[0])+","+(i[1]-o[1])+","+i[0]+","+i[1];for(var c=2;c9&&(u=3*t/Math.sqrt(u),a[o]=u*e,a[o+1]=u*r));for(o=-1;++o<=l;)u=(n[Math.min(l,o+1)][0]-n[Math.max(0,o-1)][0])/(6*(1+a[o]*a[o])),i.push([u||0,a[o]*u||0]);return i}function Fi(n){return n.length<3?xi(n):n[0]+Ai(n,Ui(n))}function Hi(n){for(var t,e,r,u=-1,i=n.length;++u=t?a(n-t):void(s.c=a)}function a(e){var u=p.active,i=p[u];i&&(i.timer.c=null,i.timer.t=NaN,--p.count,delete p[u],i.event&&i.event.interrupt.call(n,n.__data__,i.index));for(var a in p)if(r>+a){var c=p[a];c.timer.c=null,c.timer.t=NaN,--p.count,delete p[a]}s.c=o,qn(function(){return s.c&&o(e||1)&&(s.c=null,s.t=NaN),1},0,l),p.active=r,v.event&&v.event.start.call(n,n.__data__,t),g=[],v.tween.forEach(function(e,r){(r=r.call(n,n.__data__,t))&&g.push(r)}),h=v.ease,f=v.duration}function o(u){for(var i=u/f,a=h(i),o=g.length;o>0;)g[--o].call(n,a);return i>=1?(v.event&&v.event.end.call(n,n.__data__,t),--p.count?delete p[r]:delete n[e],1):void 0}var l,s,f,h,g,p=n[e]||(n[e]={active:0,count:0}),v=p[r];v||(l=u.time,s=qn(i,0,l),v=p[r]={tween:new c,time:l,timer:s,delay:u.delay,duration:u.duration,ease:u.ease,index:t},u=null,++p.count)}function na(n,t,e){n.attr("transform",function(n){var r=t(n);return"translate("+(isFinite(r)?r:e(n))+",0)"})}function ta(n,t,e){n.attr("transform",function(n){var r=t(n);return"translate(0,"+(isFinite(r)?r:e(n))+")"})}function ea(n){return n.toISOString()}function ra(n,t,e){function r(t){return n(t)}function u(n,e){var r=n[1]-n[0],u=r/e,i=oa.bisect(Gl,u);return i==Gl.length?[t.year,Ku(n.map(function(n){return n/31536e6}),e)[2]]:i?t[u/Gl[i-1]1?{floor:function(t){for(;e(t=n.floor(t));)t=ua(t-1);return t},ceil:function(t){for(;e(t=n.ceil(t));)t=ua(+t+1);return t}}:n))},r.ticks=function(n,t){var e=Yu(r.domain()),i=null==n?u(e,10):"number"==typeof n?u(e,n):!n.range&&[{range:n},t];return i&&(n=i[0],t=i[1]),n.range(e[0],ua(+e[1]+1),1>t?1:t)},r.tickFormat=function(){return e},r.copy=function(){return ra(n.copy(),t,e)},Ju(r,n)}function ua(n){return new Date(n)}function ia(n){return JSON.parse(n.responseText)}function aa(n){var t=sa.createRange();return t.selectNode(sa.body),t.createContextualFragment(n.responseText)}var oa={version:"3.5.9"},la=[].slice,ca=function(n){return la.call(n)},sa=this.document;if(sa)try{ca(sa.documentElement.childNodes)[0].nodeType}catch(fa){ca=function(n){for(var t=n.length,e=new Array(t);t--;)e[t]=n[t];return e}}if(Date.now||(Date.now=function(){return+new Date}),sa)try{sa.createElement("DIV").style.setProperty("opacity",0,"")}catch(ha){var ga=this.Element.prototype,pa=ga.setAttribute,va=ga.setAttributeNS,da=this.CSSStyleDeclaration.prototype,ma=da.setProperty;ga.setAttribute=function(n,t){pa.call(this,n,t+"")},ga.setAttributeNS=function(n,t,e){va.call(this,n,t,e+"")},da.setProperty=function(n,t,e){ma.call(this,n,t+"",e)}}oa.ascending=e,oa.descending=function(n,t){return n>t?-1:t>n?1:t>=n?0:NaN},oa.min=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u=r){e=r;break}for(;++ur&&(e=r)}else{for(;++u=r){e=r;break}for(;++ur&&(e=r)}return e},oa.max=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u=r){e=r;break}for(;++ue&&(e=r)}else{for(;++u=r){e=r;break}for(;++ue&&(e=r)}return e},oa.extent=function(n,t){var e,r,u,i=-1,a=n.length;if(1===arguments.length){for(;++i=r){e=u=r;break}for(;++ir&&(e=r),r>u&&(u=r))}else{for(;++i=r){e=u=r;break}for(;++ir&&(e=r),r>u&&(u=r))}return[e,u]},oa.sum=function(n,t){var e,r=0,i=n.length,a=-1;if(1===arguments.length)for(;++a1?l/(s-1):void 0},oa.deviation=function(){var n=oa.variance.apply(this,arguments);return n?Math.sqrt(n):n};var ya=i(e);oa.bisectLeft=ya.left,oa.bisect=oa.bisectRight=ya.right,oa.bisector=function(n){return i(1===n.length?function(t,r){return e(n(t),r)}:n)},oa.shuffle=function(n,t,e){(i=arguments.length)<3&&(e=n.length,2>i&&(t=0));for(var r,u,i=e-t;i;)u=Math.random()*i--|0,r=n[i+t],n[i+t]=n[u+t],n[u+t]=r;return n},oa.permute=function(n,t){for(var e=t.length,r=new Array(e);e--;)r[e]=n[t[e]];return r},oa.pairs=function(n){for(var t,e=0,r=n.length-1,u=n[0],i=new Array(0>r?0:r);r>e;)i[e]=[t=u,u=n[++e]];return i},oa.zip=function(){if(!(r=arguments.length))return[];for(var n=-1,t=oa.min(arguments,a),e=new Array(t);++n=0;)for(r=n[u],t=r.length;--t>=0;)e[--a]=r[t];return e};var Ma=Math.abs;oa.range=function(n,t,e){if(arguments.length<3&&(e=1,arguments.length<2&&(t=n,n=0)),(t-n)/e===1/0)throw new Error("infinite range");var r,u=[],i=o(Ma(e)),a=-1;if(n*=i,t*=i,e*=i,0>e)for(;(r=n+e*++a)>t;)u.push(r/i);else for(;(r=n+e*++a)=i.length)return r?r.call(u,a):e?a.sort(e):a;for(var l,s,f,h,g=-1,p=a.length,v=i[o++],d=new c;++g=i.length)return n;var r=[],u=a[e++];return n.forEach(function(n,u){r.push({key:n,values:t(u,e)})}),u?r.sort(function(n,t){return u(n.key,t.key)}):r}var e,r,u={},i=[],a=[];return u.map=function(t,e){return n(e,t,0)},u.entries=function(e){return t(n(oa.map,e,0),0)},u.key=function(n){return i.push(n),u},u.sortKeys=function(n){return a[i.length-1]=n,u},u.sortValues=function(n){return e=n,u},u.rollup=function(n){return r=n,u},u},oa.set=function(n){var t=new m;if(n)for(var e=0,r=n.length;r>e;++e)t.add(n[e]);return t},l(m,{has:h,add:function(n){return this._[s(n+="")]=!0,n},remove:g,values:p,size:v,empty:d,forEach:function(n){for(var t in this._)n.call(this,f(t))}}),oa.behavior={},oa.rebind=function(n,t){for(var e,r=1,u=arguments.length;++r=0&&(r=n.slice(e+1),n=n.slice(0,e)),n)return arguments.length<2?this[n].on(r):this[n].on(r,t);if(2===arguments.length){if(null==t)for(n in this)this.hasOwnProperty(n)&&this[n].on(r,null);return this}},oa.event=null,oa.requote=function(n){return n.replace(wa,"\\$&")};var wa=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g,Sa={}.__proto__?function(n,t){n.__proto__=t}:function(n,t){for(var e in t)n[e]=t[e]},ka=function(n,t){return t.querySelector(n)},Na=function(n,t){return t.querySelectorAll(n)},Ea=function(n,t){var e=n.matches||n[x(n,"matchesSelector")];return(Ea=function(n,t){return e.call(n,t)})(n,t)};"function"==typeof Sizzle&&(ka=function(n,t){return Sizzle(n,t)[0]||null},Na=Sizzle,Ea=Sizzle.matchesSelector),oa.selection=function(){return oa.select(sa.documentElement)};var Aa=oa.selection.prototype=[];Aa.select=function(n){var t,e,r,u,i=[];n=A(n);for(var a=-1,o=this.length;++a=0&&"xmlns"!==(e=n.slice(0,t))&&(n=n.slice(t+1)),Ca.hasOwnProperty(e)?{space:Ca[e],local:n}:n}},Aa.attr=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node();return n=oa.ns.qualify(n),n.local?e.getAttributeNS(n.space,n.local):e.getAttribute(n)}for(t in n)this.each(z(t,n[t]));return this}return this.each(z(n,t))},Aa.classed=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node(),r=(n=T(n)).length,u=-1;if(t=e.classList){for(;++uu){if("string"!=typeof n){2>u&&(e="");for(r in n)this.each(P(r,n[r],e));return this}if(2>u){var i=this.node();return t(i).getComputedStyle(i,null).getPropertyValue(n)}r=""}return this.each(P(n,e,r))},Aa.property=function(n,t){if(arguments.length<2){if("string"==typeof n)return this.node()[n];for(t in n)this.each(j(t,n[t]));return this}return this.each(j(n,t))},Aa.text=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.textContent=null==t?"":t}:null==n?function(){this.textContent=""}:function(){this.textContent=n}):this.node().textContent},Aa.html=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.innerHTML=null==t?"":t}:null==n?function(){this.innerHTML=""}:function(){this.innerHTML=n}):this.node().innerHTML},Aa.append=function(n){return n=U(n),this.select(function(){return this.appendChild(n.apply(this,arguments))})},Aa.insert=function(n,t){return n=U(n),t=A(t),this.select(function(){return this.insertBefore(n.apply(this,arguments),t.apply(this,arguments)||null)})},Aa.remove=function(){return this.each(F)},Aa.data=function(n,t){function e(n,e){var r,u,i,a=n.length,f=e.length,h=Math.min(a,f),g=new Array(f),p=new Array(f),v=new Array(a);if(t){var d,m=new c,y=new Array(a);for(r=-1;++rr;++r)p[r]=H(e[r]);for(;a>r;++r)v[r]=n[r]}p.update=g,p.parentNode=g.parentNode=v.parentNode=n.parentNode,o.push(p),l.push(g),s.push(v)}var r,u,i=-1,a=this.length;if(!arguments.length){for(n=new Array(a=(r=this[0]).length);++ii;i++){u.push(t=[]),t.parentNode=(e=this[i]).parentNode;for(var o=0,l=e.length;l>o;o++)(r=e[o])&&n.call(r,r.__data__,o,i)&&t.push(r)}return E(u)},Aa.order=function(){for(var n=-1,t=this.length;++n=0;)(e=r[u])&&(i&&i!==e.nextSibling&&i.parentNode.insertBefore(e,i),i=e);return this},Aa.sort=function(n){n=I.apply(this,arguments);for(var t=-1,e=this.length;++tn;n++)for(var e=this[n],r=0,u=e.length;u>r;r++){var i=e[r];if(i)return i}return null},Aa.size=function(){var n=0;return Y(this,function(){++n}),n};var za=[];oa.selection.enter=Z,oa.selection.enter.prototype=za,za.append=Aa.append,za.empty=Aa.empty,za.node=Aa.node,za.call=Aa.call,za.size=Aa.size,za.select=function(n){for(var t,e,r,u,i,a=[],o=-1,l=this.length;++or){if("string"!=typeof n){2>r&&(t=!1);for(e in n)this.each(X(e,n[e],t));return this}if(2>r)return(r=this.node()["__on"+n])&&r._;e=!1}return this.each(X(n,t,e))};var La=oa.map({mouseenter:"mouseover",mouseleave:"mouseout"});sa&&La.forEach(function(n){"on"+n in sa&&La.remove(n)});var qa,Ta=0;oa.mouse=function(n){return J(n,k())};var Ra=this.navigator&&/WebKit/.test(this.navigator.userAgent)?-1:0;oa.touch=function(n,t,e){if(arguments.length<3&&(e=t,t=k().changedTouches),t)for(var r,u=0,i=t.length;i>u;++u)if((r=t[u]).identifier===e)return J(n,r)},oa.behavior.drag=function(){function n(){this.on("mousedown.drag",i).on("touchstart.drag",a)}function e(n,t,e,i,a){return function(){function o(){var n,e,r=t(h,v);r&&(n=r[0]-M[0],e=r[1]-M[1],p|=n|e,M=r,g({type:"drag",x:r[0]+c[0],y:r[1]+c[1],dx:n,dy:e}))}function l(){t(h,v)&&(m.on(i+d,null).on(a+d,null),y(p),g({type:"dragend"}))}var c,s=this,f=oa.event.target,h=s.parentNode,g=r.of(s,arguments),p=0,v=n(),d=".drag"+(null==v?"":"-"+v),m=oa.select(e(f)).on(i+d,o).on(a+d,l),y=W(f),M=t(h,v);u?(c=u.apply(s,arguments),c=[c.x-M[0],c.y-M[1]]):c=[0,0],g({type:"dragstart"})}}var r=N(n,"drag","dragstart","dragend"),u=null,i=e(b,oa.mouse,t,"mousemove","mouseup"),a=e(G,oa.touch,y,"touchmove","touchend");return n.origin=function(t){return arguments.length?(u=t,n):u},oa.rebind(n,r,"on")},oa.touches=function(n,t){return arguments.length<2&&(t=k().touches),t?ca(t).map(function(t){var e=J(n,t);return e.identifier=t.identifier,e}):[]};var Da=1e-6,Pa=Da*Da,ja=Math.PI,Ua=2*ja,Fa=Ua-Da,Ha=ja/2,Oa=ja/180,Ia=180/ja,Ya=Math.SQRT2,Za=2,Va=4;oa.interpolateZoom=function(n,t){var e,r,u=n[0],i=n[1],a=n[2],o=t[0],l=t[1],c=t[2],s=o-u,f=l-i,h=s*s+f*f;if(Pa>h)r=Math.log(c/a)/Ya,e=function(n){return[u+n*s,i+n*f,a*Math.exp(Ya*n*r)]};else{var g=Math.sqrt(h),p=(c*c-a*a+Va*h)/(2*a*Za*g),v=(c*c-a*a-Va*h)/(2*c*Za*g),d=Math.log(Math.sqrt(p*p+1)-p),m=Math.log(Math.sqrt(v*v+1)-v);r=(m-d)/Ya,e=function(n){var t=n*r,e=rn(d),o=a/(Za*g)*(e*un(Ya*t+d)-en(d));return[u+o*s,i+o*f,a*e/rn(Ya*t+d)]}}return e.duration=1e3*r,e},oa.behavior.zoom=function(){function n(n){n.on(L,f).on($a+".zoom",g).on("dblclick.zoom",p).on(R,h)}function e(n){return[(n[0]-k.x)/k.k,(n[1]-k.y)/k.k]}function r(n){return[n[0]*k.k+k.x,n[1]*k.k+k.y]}function u(n){k.k=Math.max(A[0],Math.min(A[1],n))}function i(n,t){t=r(t),k.x+=n[0]-t[0],k.y+=n[1]-t[1]}function a(t,e,r,a){t.__chart__={x:k.x,y:k.y,k:k.k},u(Math.pow(2,a)),i(d=e,r),t=oa.select(t),C>0&&(t=t.transition().duration(C)),t.call(n.event)}function o(){b&&b.domain(x.range().map(function(n){return(n-k.x)/k.k}).map(x.invert)),w&&w.domain(_.range().map(function(n){return(n-k.y)/k.k}).map(_.invert))}function l(n){z++||n({type:"zoomstart"})}function c(n){o(),n({type:"zoom",scale:k.k,translate:[k.x,k.y]})}function s(n){--z||(n({type:"zoomend"}),d=null)}function f(){function n(){o=1,i(oa.mouse(u),h),c(a)}function r(){f.on(q,null).on(T,null),g(o),s(a)}var u=this,a=D.of(u,arguments),o=0,f=oa.select(t(u)).on(q,n).on(T,r),h=e(oa.mouse(u)),g=W(u);Ol.call(u),l(a)}function h(){function n(){var n=oa.touches(p);return g=k.k,n.forEach(function(n){n.identifier in d&&(d[n.identifier]=e(n))}),n}function t(){var t=oa.event.target;oa.select(t).on(x,r).on(b,o),_.push(t);for(var e=oa.event.changedTouches,u=0,i=e.length;i>u;++u)d[e[u].identifier]=null;var l=n(),c=Date.now();if(1===l.length){if(500>c-M){var s=l[0];a(p,s,d[s.identifier],Math.floor(Math.log(k.k)/Math.LN2)+1),S()}M=c}else if(l.length>1){var s=l[0],f=l[1],h=s[0]-f[0],g=s[1]-f[1];m=h*h+g*g}}function r(){var n,t,e,r,a=oa.touches(p);Ol.call(p);for(var o=0,l=a.length;l>o;++o,r=null)if(e=a[o],r=d[e.identifier]){if(t)break;n=e,t=r}if(r){var s=(s=e[0]-n[0])*s+(s=e[1]-n[1])*s,f=m&&Math.sqrt(s/m);n=[(n[0]+e[0])/2,(n[1]+e[1])/2],t=[(t[0]+r[0])/2,(t[1]+r[1])/2],u(f*g)}M=null,i(n,t),c(v)}function o(){if(oa.event.touches.length){for(var t=oa.event.changedTouches,e=0,r=t.length;r>e;++e)delete d[t[e].identifier];for(var u in d)return void n()}oa.selectAll(_).on(y,null),w.on(L,f).on(R,h),N(),s(v)}var g,p=this,v=D.of(p,arguments),d={},m=0,y=".zoom-"+oa.event.changedTouches[0].identifier,x="touchmove"+y,b="touchend"+y,_=[],w=oa.select(p),N=W(p);t(),l(v),w.on(L,null).on(R,t)}function g(){var n=D.of(this,arguments);y?clearTimeout(y):(Ol.call(this),v=e(d=m||oa.mouse(this)),l(n)),y=setTimeout(function(){y=null,s(n)},50),S(),u(Math.pow(2,.002*Xa())*k.k),i(d,v),c(n)}function p(){var n=oa.mouse(this),t=Math.log(k.k)/Math.LN2;a(this,n,e(n),oa.event.shiftKey?Math.ceil(t)-1:Math.floor(t)+1)}var v,d,m,y,M,x,b,_,w,k={x:0,y:0,k:1},E=[960,500],A=Ba,C=250,z=0,L="mousedown.zoom",q="mousemove.zoom",T="mouseup.zoom",R="touchstart.zoom",D=N(n,"zoomstart","zoom","zoomend");return $a||($a="onwheel"in sa?(Xa=function(){return-oa.event.deltaY*(oa.event.deltaMode?120:1)},"wheel"):"onmousewheel"in sa?(Xa=function(){return oa.event.wheelDelta},"mousewheel"):(Xa=function(){return-oa.event.detail},"MozMousePixelScroll")),n.event=function(n){n.each(function(){var n=D.of(this,arguments),t=k;Fl?oa.select(this).transition().each("start.zoom",function(){k=this.__chart__||{x:0,y:0,k:1},l(n)}).tween("zoom:zoom",function(){var e=E[0],r=E[1],u=d?d[0]:e/2,i=d?d[1]:r/2,a=oa.interpolateZoom([(u-k.x)/k.k,(i-k.y)/k.k,e/k.k],[(u-t.x)/t.k,(i-t.y)/t.k,e/t.k]);return function(t){var r=a(t),o=e/r[2];this.__chart__=k={x:u-r[0]*o,y:i-r[1]*o,k:o},c(n)}}).each("interrupt.zoom",function(){s(n)}).each("end.zoom",function(){s(n)}):(this.__chart__=k,l(n),c(n),s(n))})},n.translate=function(t){return arguments.length?(k={x:+t[0],y:+t[1],k:k.k},o(),n):[k.x,k.y]},n.scale=function(t){return arguments.length?(k={x:k.x,y:k.y,k:null},u(+t),o(),n):k.k},n.scaleExtent=function(t){return arguments.length?(A=null==t?Ba:[+t[0],+t[1]],n):A},n.center=function(t){return arguments.length?(m=t&&[+t[0],+t[1]],n):m},n.size=function(t){return arguments.length?(E=t&&[+t[0],+t[1]],n):E},n.duration=function(t){return arguments.length?(C=+t,n):C},n.x=function(t){return arguments.length?(b=t,x=t.copy(),k={x:0,y:0,k:1},n):b},n.y=function(t){return arguments.length?(w=t,_=t.copy(),k={x:0,y:0,k:1},n):w},oa.rebind(n,D,"on")};var Xa,$a,Ba=[0,1/0];oa.color=on,on.prototype.toString=function(){return this.rgb()+""},oa.hsl=ln;var Wa=ln.prototype=new on;Wa.brighter=function(n){return n=Math.pow(.7,arguments.length?n:1),new ln(this.h,this.s,this.l/n)},Wa.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new ln(this.h,this.s,n*this.l)},Wa.rgb=function(){return cn(this.h,this.s,this.l)},oa.hcl=sn;var Ja=sn.prototype=new on;Ja.brighter=function(n){return new sn(this.h,this.c,Math.min(100,this.l+Ga*(arguments.length?n:1)))},Ja.darker=function(n){return new sn(this.h,this.c,Math.max(0,this.l-Ga*(arguments.length?n:1)))},Ja.rgb=function(){return fn(this.h,this.c,this.l).rgb()},oa.lab=hn;var Ga=18,Ka=.95047,Qa=1,no=1.08883,to=hn.prototype=new on;to.brighter=function(n){return new hn(Math.min(100,this.l+Ga*(arguments.length?n:1)),this.a,this.b)},to.darker=function(n){return new hn(Math.max(0,this.l-Ga*(arguments.length?n:1)),this.a,this.b)},to.rgb=function(){return gn(this.l,this.a,this.b)},oa.rgb=yn;var eo=yn.prototype=new on;eo.brighter=function(n){n=Math.pow(.7,arguments.length?n:1);var t=this.r,e=this.g,r=this.b,u=30;return t||e||r?(t&&u>t&&(t=u),e&&u>e&&(e=u),r&&u>r&&(r=u),new yn(Math.min(255,t/n),Math.min(255,e/n),Math.min(255,r/n))):new yn(u,u,u)},eo.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new yn(n*this.r,n*this.g,n*this.b)},eo.hsl=function(){return wn(this.r,this.g,this.b)},eo.toString=function(){return"#"+bn(this.r)+bn(this.g)+bn(this.b)};var ro=oa.map({aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074});ro.forEach(function(n,t){ro.set(n,Mn(t))}),oa.functor=En,oa.xhr=An(y),oa.dsv=function(n,t){function e(n,e,i){arguments.length<3&&(i=e,e=null);var a=Cn(n,t,null==e?r:u(e),i);return a.row=function(n){return arguments.length?a.response(null==(e=n)?r:u(n)):e},a}function r(n){return e.parse(n.responseText)}function u(n){return function(t){return e.parse(t.responseText,n)}}function i(t){return t.map(a).join(n)}function a(n){return o.test(n)?'"'+n.replace(/\"/g,'""')+'"':n}var o=new RegExp('["'+n+"\n]"),l=n.charCodeAt(0);return e.parse=function(n,t){var r;return e.parseRows(n,function(n,e){if(r)return r(n,e-1);var u=new Function("d","return {"+n.map(function(n,t){return JSON.stringify(n)+": d["+t+"]"}).join(",")+"}");r=t?function(n,e){return t(u(n),e)}:u})},e.parseRows=function(n,t){function e(){if(s>=c)return a;if(u)return u=!1,i;var t=s;if(34===n.charCodeAt(t)){for(var e=t;e++s;){var r=n.charCodeAt(s++),o=1;if(10===r)u=!0;else if(13===r)u=!0,10===n.charCodeAt(s)&&(++s,++o);else if(r!==l)continue;return n.slice(t,s-o)}return n.slice(t)}for(var r,u,i={},a={},o=[],c=n.length,s=0,f=0;(r=e())!==a;){for(var h=[];r!==i&&r!==a;)h.push(r),r=e();t&&null==(h=t(h,f++))||o.push(h)}return o},e.format=function(t){if(Array.isArray(t[0]))return e.formatRows(t);var r=new m,u=[];return t.forEach(function(n){for(var t in n)r.has(t)||u.push(r.add(t))}),[u.map(a).join(n)].concat(t.map(function(t){return u.map(function(n){return a(t[n])}).join(n)})).join("\n")},e.formatRows=function(n){return n.map(i).join("\n")},e},oa.csv=oa.dsv(",","text/csv"),oa.tsv=oa.dsv(" ","text/tab-separated-values");var uo,io,ao,oo,lo=this[x(this,"requestAnimationFrame")]||function(n){setTimeout(n,17)};oa.timer=function(){qn.apply(this,arguments)},oa.timer.flush=function(){Rn(),Dn()},oa.round=function(n,t){return t?Math.round(n*(t=Math.pow(10,t)))/t:Math.round(n)};var co=["y","z","a","f","p","n","\xb5","m","","k","M","G","T","P","E","Z","Y"].map(jn);oa.formatPrefix=function(n,t){var e=0;return(n=+n)&&(0>n&&(n*=-1),t&&(n=oa.round(n,Pn(n,t))),e=1+Math.floor(1e-12+Math.log(n)/Math.LN10),e=Math.max(-24,Math.min(24,3*Math.floor((e-1)/3)))),co[8+e/3]};var so=/(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i,fo=oa.map({b:function(n){return n.toString(2)},c:function(n){return String.fromCharCode(n)},o:function(n){return n.toString(8)},x:function(n){return n.toString(16)},X:function(n){return n.toString(16).toUpperCase()},g:function(n,t){return n.toPrecision(t)},e:function(n,t){return n.toExponential(t)},f:function(n,t){return n.toFixed(t)},r:function(n,t){return(n=oa.round(n,Pn(n,t))).toFixed(Math.max(0,Math.min(20,Pn(n*(1+1e-15),t))))}}),ho=oa.time={},go=Date;Hn.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){po.setUTCDate.apply(this._,arguments)},setDay:function(){po.setUTCDay.apply(this._,arguments)},setFullYear:function(){po.setUTCFullYear.apply(this._,arguments)},setHours:function(){po.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){po.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){po.setUTCMinutes.apply(this._,arguments)},setMonth:function(){po.setUTCMonth.apply(this._,arguments)},setSeconds:function(){po.setUTCSeconds.apply(this._,arguments)},setTime:function(){po.setTime.apply(this._,arguments)}};var po=Date.prototype;ho.year=On(function(n){return n=ho.day(n),n.setMonth(0,1),n},function(n,t){n.setFullYear(n.getFullYear()+t)},function(n){return n.getFullYear()}),ho.years=ho.year.range,ho.years.utc=ho.year.utc.range,ho.day=On(function(n){var t=new go(2e3,0);return t.setFullYear(n.getFullYear(),n.getMonth(),n.getDate()),t},function(n,t){n.setDate(n.getDate()+t)},function(n){return n.getDate()-1}),ho.days=ho.day.range,ho.days.utc=ho.day.utc.range,ho.dayOfYear=function(n){var t=ho.year(n);return Math.floor((n-t-6e4*(n.getTimezoneOffset()-t.getTimezoneOffset()))/864e5)},["sunday","monday","tuesday","wednesday","thursday","friday","saturday"].forEach(function(n,t){t=7-t;var e=ho[n]=On(function(n){return(n=ho.day(n)).setDate(n.getDate()-(n.getDay()+t)%7),n},function(n,t){n.setDate(n.getDate()+7*Math.floor(t))},function(n){var e=ho.year(n).getDay();return Math.floor((ho.dayOfYear(n)+(e+t)%7)/7)-(e!==t)});ho[n+"s"]=e.range,ho[n+"s"].utc=e.utc.range,ho[n+"OfYear"]=function(n){var e=ho.year(n).getDay();return Math.floor((ho.dayOfYear(n)+(e+t)%7)/7)}}),ho.week=ho.sunday,ho.weeks=ho.sunday.range,ho.weeks.utc=ho.sunday.utc.range,ho.weekOfYear=ho.sundayOfYear;var vo={"-":"",_:" ",0:"0"},mo=/^\s*\d+/,yo=/^%/;oa.locale=function(n){return{numberFormat:Un(n),timeFormat:Yn(n)}};var Mo=oa.locale({decimal:".",thousands:",",grouping:[3],currency:["$",""],dateTime:"%a %b %e %X %Y",date:"%m/%d/%Y",time:"%H:%M:%S",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"], +shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});oa.format=Mo.numberFormat,oa.geo={},st.prototype={s:0,t:0,add:function(n){ft(n,this.t,xo),ft(xo.s,this.s,this),this.s?this.t+=xo.t:this.s=xo.t},reset:function(){this.s=this.t=0},valueOf:function(){return this.s}};var xo=new st;oa.geo.stream=function(n,t){n&&bo.hasOwnProperty(n.type)?bo[n.type](n,t):ht(n,t)};var bo={Feature:function(n,t){ht(n.geometry,t)},FeatureCollection:function(n,t){for(var e=n.features,r=-1,u=e.length;++rn?4*ja+n:n,ko.lineStart=ko.lineEnd=ko.point=b}};oa.geo.bounds=function(){function n(n,t){M.push(x=[s=n,h=n]),f>t&&(f=t),t>g&&(g=t)}function t(t,e){var r=dt([t*Oa,e*Oa]);if(m){var u=yt(m,r),i=[u[1],-u[0],0],a=yt(i,u);bt(a),a=_t(a);var l=t-p,c=l>0?1:-1,v=a[0]*Ia*c,d=Ma(l)>180;if(d^(v>c*p&&c*t>v)){var y=a[1]*Ia;y>g&&(g=y)}else if(v=(v+360)%360-180,d^(v>c*p&&c*t>v)){var y=-a[1]*Ia;f>y&&(f=y)}else f>e&&(f=e),e>g&&(g=e);d?p>t?o(s,t)>o(s,h)&&(h=t):o(t,h)>o(s,h)&&(s=t):h>=s?(s>t&&(s=t),t>h&&(h=t)):t>p?o(s,t)>o(s,h)&&(h=t):o(t,h)>o(s,h)&&(s=t)}else n(t,e);m=r,p=t}function e(){b.point=t}function r(){x[0]=s,x[1]=h,b.point=n,m=null}function u(n,e){if(m){var r=n-p;y+=Ma(r)>180?r+(r>0?360:-360):r}else v=n,d=e;ko.point(n,e),t(n,e)}function i(){ko.lineStart()}function a(){u(v,d),ko.lineEnd(),Ma(y)>Da&&(s=-(h=180)),x[0]=s,x[1]=h,m=null}function o(n,t){return(t-=n)<0?t+360:t}function l(n,t){return n[0]-t[0]}function c(n,t){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:nSo?(s=-(h=180),f=-(g=90)):y>Da?g=90:-Da>y&&(f=-90),x[0]=s,x[1]=h}};return function(n){g=h=-(s=f=1/0),M=[],oa.geo.stream(n,b);var t=M.length;if(t){M.sort(l);for(var e,r=1,u=M[0],i=[u];t>r;++r)e=M[r],c(e[0],u)||c(e[1],u)?(o(u[0],e[1])>o(u[0],u[1])&&(u[1]=e[1]),o(e[0],u[1])>o(u[0],u[1])&&(u[0]=e[0])):i.push(u=e);for(var a,e,p=-(1/0),t=i.length-1,r=0,u=i[t];t>=r;u=e,++r)e=i[r],(a=o(u[1],e[0]))>p&&(p=a,s=e[0],h=u[1])}return M=x=null,s===1/0||f===1/0?[[NaN,NaN],[NaN,NaN]]:[[s,f],[h,g]]}}(),oa.geo.centroid=function(n){No=Eo=Ao=Co=zo=Lo=qo=To=Ro=Do=Po=0,oa.geo.stream(n,jo);var t=Ro,e=Do,r=Po,u=t*t+e*e+r*r;return Pa>u&&(t=Lo,e=qo,r=To,Da>Eo&&(t=Ao,e=Co,r=zo),u=t*t+e*e+r*r,Pa>u)?[NaN,NaN]:[Math.atan2(e,t)*Ia,tn(r/Math.sqrt(u))*Ia]};var No,Eo,Ao,Co,zo,Lo,qo,To,Ro,Do,Po,jo={sphere:b,point:St,lineStart:Nt,lineEnd:Et,polygonStart:function(){jo.lineStart=At},polygonEnd:function(){jo.lineStart=Nt}},Uo=Rt(zt,Ut,Ht,[-ja,-ja/2]),Fo=1e9;oa.geo.clipExtent=function(){var n,t,e,r,u,i,a={stream:function(n){return u&&(u.valid=!1),u=i(n),u.valid=!0,u},extent:function(o){return arguments.length?(i=Zt(n=+o[0][0],t=+o[0][1],e=+o[1][0],r=+o[1][1]),u&&(u.valid=!1,u=null),a):[[n,t],[e,r]]}};return a.extent([[0,0],[960,500]])},(oa.geo.conicEqualArea=function(){return Vt(Xt)}).raw=Xt,oa.geo.albers=function(){return oa.geo.conicEqualArea().rotate([96,0]).center([-.6,38.7]).parallels([29.5,45.5]).scale(1070)},oa.geo.albersUsa=function(){function n(n){var i=n[0],a=n[1];return t=null,e(i,a),t||(r(i,a),t)||u(i,a),t}var t,e,r,u,i=oa.geo.albers(),a=oa.geo.conicEqualArea().rotate([154,0]).center([-2,58.5]).parallels([55,65]),o=oa.geo.conicEqualArea().rotate([157,0]).center([-3,19.9]).parallels([8,18]),l={point:function(n,e){t=[n,e]}};return n.invert=function(n){var t=i.scale(),e=i.translate(),r=(n[0]-e[0])/t,u=(n[1]-e[1])/t;return(u>=.12&&.234>u&&r>=-.425&&-.214>r?a:u>=.166&&.234>u&&r>=-.214&&-.115>r?o:i).invert(n)},n.stream=function(n){var t=i.stream(n),e=a.stream(n),r=o.stream(n);return{point:function(n,u){t.point(n,u),e.point(n,u),r.point(n,u)},sphere:function(){t.sphere(),e.sphere(),r.sphere()},lineStart:function(){t.lineStart(),e.lineStart(),r.lineStart()},lineEnd:function(){t.lineEnd(),e.lineEnd(),r.lineEnd()},polygonStart:function(){t.polygonStart(),e.polygonStart(),r.polygonStart()},polygonEnd:function(){t.polygonEnd(),e.polygonEnd(),r.polygonEnd()}}},n.precision=function(t){return arguments.length?(i.precision(t),a.precision(t),o.precision(t),n):i.precision()},n.scale=function(t){return arguments.length?(i.scale(t),a.scale(.35*t),o.scale(t),n.translate(i.translate())):i.scale()},n.translate=function(t){if(!arguments.length)return i.translate();var c=i.scale(),s=+t[0],f=+t[1];return e=i.translate(t).clipExtent([[s-.455*c,f-.238*c],[s+.455*c,f+.238*c]]).stream(l).point,r=a.translate([s-.307*c,f+.201*c]).clipExtent([[s-.425*c+Da,f+.12*c+Da],[s-.214*c-Da,f+.234*c-Da]]).stream(l).point,u=o.translate([s-.205*c,f+.212*c]).clipExtent([[s-.214*c+Da,f+.166*c+Da],[s-.115*c-Da,f+.234*c-Da]]).stream(l).point,n},n.scale(1070)};var Ho,Oo,Io,Yo,Zo,Vo,Xo={point:b,lineStart:b,lineEnd:b,polygonStart:function(){Oo=0,Xo.lineStart=$t},polygonEnd:function(){Xo.lineStart=Xo.lineEnd=Xo.point=b,Ho+=Ma(Oo/2)}},$o={point:Bt,lineStart:b,lineEnd:b,polygonStart:b,polygonEnd:b},Bo={point:Gt,lineStart:Kt,lineEnd:Qt,polygonStart:function(){Bo.lineStart=ne},polygonEnd:function(){Bo.point=Gt,Bo.lineStart=Kt,Bo.lineEnd=Qt}};oa.geo.path=function(){function n(n){return n&&("function"==typeof o&&i.pointRadius(+o.apply(this,arguments)),a&&a.valid||(a=u(i)),oa.geo.stream(n,a)),i.result()}function t(){return a=null,n}var e,r,u,i,a,o=4.5;return n.area=function(n){return Ho=0,oa.geo.stream(n,u(Xo)),Ho},n.centroid=function(n){return Ao=Co=zo=Lo=qo=To=Ro=Do=Po=0,oa.geo.stream(n,u(Bo)),Po?[Ro/Po,Do/Po]:To?[Lo/To,qo/To]:zo?[Ao/zo,Co/zo]:[NaN,NaN]},n.bounds=function(n){return Zo=Vo=-(Io=Yo=1/0),oa.geo.stream(n,u($o)),[[Io,Yo],[Zo,Vo]]},n.projection=function(n){return arguments.length?(u=(e=n)?n.stream||re(n):y,t()):e},n.context=function(n){return arguments.length?(i=null==(r=n)?new Wt:new te(n),"function"!=typeof o&&i.pointRadius(o),t()):r},n.pointRadius=function(t){return arguments.length?(o="function"==typeof t?t:(i.pointRadius(+t),+t),n):o},n.projection(oa.geo.albersUsa()).context(null)},oa.geo.transform=function(n){return{stream:function(t){var e=new ue(t);for(var r in n)e[r]=n[r];return e}}},ue.prototype={point:function(n,t){this.stream.point(n,t)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}},oa.geo.projection=ae,oa.geo.projectionMutator=oe,(oa.geo.equirectangular=function(){return ae(ce)}).raw=ce.invert=ce,oa.geo.rotation=function(n){function t(t){return t=n(t[0]*Oa,t[1]*Oa),t[0]*=Ia,t[1]*=Ia,t}return n=fe(n[0]%360*Oa,n[1]*Oa,n.length>2?n[2]*Oa:0),t.invert=function(t){return t=n.invert(t[0]*Oa,t[1]*Oa),t[0]*=Ia,t[1]*=Ia,t},t},se.invert=ce,oa.geo.circle=function(){function n(){var n="function"==typeof r?r.apply(this,arguments):r,t=fe(-n[0]*Oa,-n[1]*Oa,0).invert,u=[];return e(null,null,1,{point:function(n,e){u.push(n=t(n,e)),n[0]*=Ia,n[1]*=Ia}}),{type:"Polygon",coordinates:[u]}}var t,e,r=[0,0],u=6;return n.origin=function(t){return arguments.length?(r=t,n):r},n.angle=function(r){return arguments.length?(e=ve((t=+r)*Oa,u*Oa),n):t},n.precision=function(r){return arguments.length?(e=ve(t*Oa,(u=+r)*Oa),n):u},n.angle(90)},oa.geo.distance=function(n,t){var e,r=(t[0]-n[0])*Oa,u=n[1]*Oa,i=t[1]*Oa,a=Math.sin(r),o=Math.cos(r),l=Math.sin(u),c=Math.cos(u),s=Math.sin(i),f=Math.cos(i);return Math.atan2(Math.sqrt((e=f*a)*e+(e=c*s-l*f*o)*e),l*s+c*f*o)},oa.geo.graticule=function(){function n(){return{type:"MultiLineString",coordinates:t()}}function t(){return oa.range(Math.ceil(i/d)*d,u,d).map(h).concat(oa.range(Math.ceil(c/m)*m,l,m).map(g)).concat(oa.range(Math.ceil(r/p)*p,e,p).filter(function(n){return Ma(n%d)>Da}).map(s)).concat(oa.range(Math.ceil(o/v)*v,a,v).filter(function(n){return Ma(n%m)>Da}).map(f))}var e,r,u,i,a,o,l,c,s,f,h,g,p=10,v=p,d=90,m=360,y=2.5;return n.lines=function(){return t().map(function(n){return{type:"LineString",coordinates:n}})},n.outline=function(){return{type:"Polygon",coordinates:[h(i).concat(g(l).slice(1),h(u).reverse().slice(1),g(c).reverse().slice(1))]}},n.extent=function(t){return arguments.length?n.majorExtent(t).minorExtent(t):n.minorExtent()},n.majorExtent=function(t){return arguments.length?(i=+t[0][0],u=+t[1][0],c=+t[0][1],l=+t[1][1],i>u&&(t=i,i=u,u=t),c>l&&(t=c,c=l,l=t),n.precision(y)):[[i,c],[u,l]]},n.minorExtent=function(t){return arguments.length?(r=+t[0][0],e=+t[1][0],o=+t[0][1],a=+t[1][1],r>e&&(t=r,r=e,e=t),o>a&&(t=o,o=a,a=t),n.precision(y)):[[r,o],[e,a]]},n.step=function(t){return arguments.length?n.majorStep(t).minorStep(t):n.minorStep()},n.majorStep=function(t){return arguments.length?(d=+t[0],m=+t[1],n):[d,m]},n.minorStep=function(t){return arguments.length?(p=+t[0],v=+t[1],n):[p,v]},n.precision=function(t){return arguments.length?(y=+t,s=me(o,a,90),f=ye(r,e,y),h=me(c,l,90),g=ye(i,u,y),n):y},n.majorExtent([[-180,-90+Da],[180,90-Da]]).minorExtent([[-180,-80-Da],[180,80+Da]])},oa.geo.greatArc=function(){function n(){return{type:"LineString",coordinates:[t||r.apply(this,arguments),e||u.apply(this,arguments)]}}var t,e,r=Me,u=xe;return n.distance=function(){return oa.geo.distance(t||r.apply(this,arguments),e||u.apply(this,arguments))},n.source=function(e){return arguments.length?(r=e,t="function"==typeof e?null:e,n):r},n.target=function(t){return arguments.length?(u=t,e="function"==typeof t?null:t,n):u},n.precision=function(){return arguments.length?n:0},n},oa.geo.interpolate=function(n,t){return be(n[0]*Oa,n[1]*Oa,t[0]*Oa,t[1]*Oa)},oa.geo.length=function(n){return Wo=0,oa.geo.stream(n,Jo),Wo};var Wo,Jo={sphere:b,point:b,lineStart:_e,lineEnd:b,polygonStart:b,polygonEnd:b},Go=we(function(n){return Math.sqrt(2/(1+n))},function(n){return 2*Math.asin(n/2)});(oa.geo.azimuthalEqualArea=function(){return ae(Go)}).raw=Go;var Ko=we(function(n){var t=Math.acos(n);return t&&t/Math.sin(t)},y);(oa.geo.azimuthalEquidistant=function(){return ae(Ko)}).raw=Ko,(oa.geo.conicConformal=function(){return Vt(Se)}).raw=Se,(oa.geo.conicEquidistant=function(){return Vt(ke)}).raw=ke;var Qo=we(function(n){return 1/n},Math.atan);(oa.geo.gnomonic=function(){return ae(Qo)}).raw=Qo,Ne.invert=function(n,t){return[n,2*Math.atan(Math.exp(t))-Ha]},(oa.geo.mercator=function(){return Ee(Ne)}).raw=Ne;var nl=we(function(){return 1},Math.asin);(oa.geo.orthographic=function(){return ae(nl)}).raw=nl;var tl=we(function(n){return 1/(1+n)},function(n){return 2*Math.atan(n)});(oa.geo.stereographic=function(){return ae(tl)}).raw=tl,Ae.invert=function(n,t){return[-t,2*Math.atan(Math.exp(n))-Ha]},(oa.geo.transverseMercator=function(){var n=Ee(Ae),t=n.center,e=n.rotate;return n.center=function(n){return n?t([-n[1],n[0]]):(n=t(),[n[1],-n[0]])},n.rotate=function(n){return n?e([n[0],n[1],n.length>2?n[2]+90:90]):(n=e(),[n[0],n[1],n[2]-90])},e([0,0,90])}).raw=Ae,oa.geom={},oa.geom.hull=function(n){function t(n){if(n.length<3)return[];var t,u=En(e),i=En(r),a=n.length,o=[],l=[];for(t=0;a>t;t++)o.push([+u.call(this,n[t],t),+i.call(this,n[t],t),t]);for(o.sort(qe),t=0;a>t;t++)l.push([o[t][0],-o[t][1]]);var c=Le(o),s=Le(l),f=s[0]===c[0],h=s[s.length-1]===c[c.length-1],g=[];for(t=c.length-1;t>=0;--t)g.push(n[o[c[t]][2]]);for(t=+f;t=r&&c.x<=i&&c.y>=u&&c.y<=a?[[r,a],[i,a],[i,u],[r,u]]:[];s.point=n[o]}),t}function e(n){return n.map(function(n,t){return{x:Math.round(i(n,t)/Da)*Da,y:Math.round(a(n,t)/Da)*Da,i:t}})}var r=Ce,u=ze,i=r,a=u,o=sl;return n?t(n):(t.links=function(n){return or(e(n)).edges.filter(function(n){return n.l&&n.r}).map(function(t){return{source:n[t.l.i],target:n[t.r.i]}})},t.triangles=function(n){var t=[];return or(e(n)).cells.forEach(function(e,r){for(var u,i,a=e.site,o=e.edges.sort(Ve),l=-1,c=o.length,s=o[c-1].edge,f=s.l===a?s.r:s.l;++l=c,h=r>=s,g=h<<1|f;n.leaf=!1,n=n.nodes[g]||(n.nodes[g]=hr()),f?u=c:o=c,h?a=s:l=s,i(n,t,e,r,u,a,o,l)}var s,f,h,g,p,v,d,m,y,M=En(o),x=En(l);if(null!=t)v=t,d=e,m=r,y=u;else if(m=y=-(v=d=1/0),f=[],h=[],p=n.length,a)for(g=0;p>g;++g)s=n[g],s.xm&&(m=s.x),s.y>y&&(y=s.y),f.push(s.x),h.push(s.y);else for(g=0;p>g;++g){var b=+M(s=n[g],g),_=+x(s,g);v>b&&(v=b),d>_&&(d=_),b>m&&(m=b),_>y&&(y=_),f.push(b),h.push(_)}var w=m-v,S=y-d;w>S?y=d+w:m=v+S;var k=hr();if(k.add=function(n){i(k,n,+M(n,++g),+x(n,g),v,d,m,y)},k.visit=function(n){gr(n,k,v,d,m,y)},k.find=function(n){return pr(k,n[0],n[1],v,d,m,y)},g=-1,null==t){for(;++g=0?n.slice(0,t):n,r=t>=0?n.slice(t+1):"in";return e=pl.get(e)||gl,r=vl.get(r)||y,br(r(e.apply(null,la.call(arguments,1))))},oa.interpolateHcl=Rr,oa.interpolateHsl=Dr,oa.interpolateLab=Pr,oa.interpolateRound=jr,oa.transform=function(n){var t=sa.createElementNS(oa.ns.prefix.svg,"g");return(oa.transform=function(n){if(null!=n){t.setAttribute("transform",n);var e=t.transform.baseVal.consolidate()}return new Ur(e?e.matrix:dl)})(n)},Ur.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var dl={a:1,b:0,c:0,d:1,e:0,f:0};oa.interpolateTransform=$r,oa.layout={},oa.layout.bundle=function(){return function(n){for(var t=[],e=-1,r=n.length;++eo*o/m){if(v>l){var c=t.charge/l;n.px-=i*c,n.py-=a*c}return!0}if(t.point&&l&&v>l){var c=t.pointCharge/l;n.px-=i*c,n.py-=a*c}}return!t.charge}}function t(n){n.px=oa.event.x,n.py=oa.event.y,l.resume()}var e,r,u,i,a,o,l={},c=oa.dispatch("start","tick","end"),s=[1,1],f=.9,h=ml,g=yl,p=-30,v=Ml,d=.1,m=.64,M=[],x=[];return l.tick=function(){if((u*=.99)<.005)return e=null,c.end({type:"end",alpha:u=0}),!0;var t,r,l,h,g,v,m,y,b,_=M.length,w=x.length;for(r=0;w>r;++r)l=x[r],h=l.source,g=l.target,y=g.x-h.x,b=g.y-h.y,(v=y*y+b*b)&&(v=u*a[r]*((v=Math.sqrt(v))-i[r])/v,y*=v,b*=v,g.x-=y*(m=h.weight+g.weight?h.weight/(h.weight+g.weight):.5),g.y-=b*m,h.x+=y*(m=1-m),h.y+=b*m);if((m=u*d)&&(y=s[0]/2,b=s[1]/2,r=-1,m))for(;++r<_;)l=M[r],l.x+=(y-l.x)*m,l.y+=(b-l.y)*m;if(p)for(ru(t=oa.geom.quadtree(M),u,o),r=-1;++r<_;)(l=M[r]).fixed||t.visit(n(l));for(r=-1;++r<_;)l=M[r],l.fixed?(l.x=l.px,l.y=l.py):(l.x-=(l.px-(l.px=l.x))*f,l.y-=(l.py-(l.py=l.y))*f);c.tick({type:"tick",alpha:u})},l.nodes=function(n){return arguments.length?(M=n,l):M},l.links=function(n){return arguments.length?(x=n,l):x},l.size=function(n){return arguments.length?(s=n,l):s},l.linkDistance=function(n){return arguments.length?(h="function"==typeof n?n:+n,l):h},l.distance=l.linkDistance,l.linkStrength=function(n){return arguments.length?(g="function"==typeof n?n:+n,l):g},l.friction=function(n){return arguments.length?(f=+n,l):f},l.charge=function(n){return arguments.length?(p="function"==typeof n?n:+n,l):p},l.chargeDistance=function(n){return arguments.length?(v=n*n,l):Math.sqrt(v)},l.gravity=function(n){return arguments.length?(d=+n,l):d},l.theta=function(n){return arguments.length?(m=n*n,l):Math.sqrt(m)},l.alpha=function(n){return arguments.length?(n=+n,u?n>0?u=n:(e.c=null,e.t=NaN,e=null,c.start({type:"end",alpha:u=0})):n>0&&(c.start({type:"start",alpha:u=n}),e=qn(l.tick)),l):u},l.start=function(){function n(n,r){if(!e){for(e=new Array(u),l=0;u>l;++l)e[l]=[];for(l=0;c>l;++l){var i=x[l];e[i.source.index].push(i.target),e[i.target.index].push(i.source)}}for(var a,o=e[t],l=-1,s=o.length;++lt;++t)(r=M[t]).index=t,r.weight=0;for(t=0;c>t;++t)r=x[t],"number"==typeof r.source&&(r.source=M[r.source]),"number"==typeof r.target&&(r.target=M[r.target]),++r.source.weight,++r.target.weight;for(t=0;u>t;++t)r=M[t],isNaN(r.x)&&(r.x=n("x",f)),isNaN(r.y)&&(r.y=n("y",v)),isNaN(r.px)&&(r.px=r.x),isNaN(r.py)&&(r.py=r.y);if(i=[],"function"==typeof h)for(t=0;c>t;++t)i[t]=+h.call(this,x[t],t);else for(t=0;c>t;++t)i[t]=h;if(a=[],"function"==typeof g)for(t=0;c>t;++t)a[t]=+g.call(this,x[t],t);else for(t=0;c>t;++t)a[t]=g;if(o=[],"function"==typeof p)for(t=0;u>t;++t)o[t]=+p.call(this,M[t],t);else for(t=0;u>t;++t)o[t]=p;return l.resume()},l.resume=function(){return l.alpha(.1)},l.stop=function(){return l.alpha(0)},l.drag=function(){return r||(r=oa.behavior.drag().origin(y).on("dragstart.force",Qr).on("drag.force",t).on("dragend.force",nu)),arguments.length?void this.on("mouseover.force",tu).on("mouseout.force",eu).call(r):r},oa.rebind(l,c,"on")};var ml=20,yl=1,Ml=1/0;oa.layout.hierarchy=function(){function n(u){var i,a=[u],o=[];for(u.depth=0;null!=(i=a.pop());)if(o.push(i),(c=e.call(n,i,i.depth))&&(l=c.length)){for(var l,c,s;--l>=0;)a.push(s=c[l]),s.parent=i,s.depth=i.depth+1;r&&(i.value=0),i.children=c}else r&&(i.value=+r.call(n,i,i.depth)||0),delete i.children;return au(u,function(n){var e,u;t&&(e=n.children)&&e.sort(t),r&&(u=n.parent)&&(u.value+=n.value)}),o}var t=cu,e=ou,r=lu;return n.sort=function(e){return arguments.length?(t=e,n):t},n.children=function(t){return arguments.length?(e=t,n):e},n.value=function(t){return arguments.length?(r=t,n):r},n.revalue=function(t){return r&&(iu(t,function(n){n.children&&(n.value=0)}),au(t,function(t){var e;t.children||(t.value=+r.call(n,t,t.depth)||0),(e=t.parent)&&(e.value+=t.value)})),t},n},oa.layout.partition=function(){function n(t,e,r,u){var i=t.children;if(t.x=e,t.y=t.depth*u,t.dx=r,t.dy=u,i&&(a=i.length)){var a,o,l,c=-1;for(r=t.value?r/t.value:0;++cf?-1:1),p=oa.sum(c),v=p?(f-l*g)/p:0,d=oa.range(l),m=[];return null!=e&&d.sort(e===xl?function(n,t){return c[t]-c[n]}:function(n,t){return e(a[n],a[t])}),d.forEach(function(n){m[n]={data:a[n],value:o=c[n],startAngle:s,endAngle:s+=o*v+g,padAngle:h}}),m}var t=Number,e=xl,r=0,u=Ua,i=0;return n.value=function(e){return arguments.length?(t=e,n):t},n.sort=function(t){return arguments.length?(e=t,n):e},n.startAngle=function(t){return arguments.length?(r=t,n):r},n.endAngle=function(t){return arguments.length?(u=t,n):u},n.padAngle=function(t){return arguments.length?(i=t,n):i},n};var xl={};oa.layout.stack=function(){function n(o,l){if(!(h=o.length))return o;var c=o.map(function(e,r){return t.call(n,e,r)}),s=c.map(function(t){return t.map(function(t,e){return[i.call(n,t,e),a.call(n,t,e)]})}),f=e.call(n,s,l);c=oa.permute(c,f),s=oa.permute(s,f);var h,g,p,v,d=r.call(n,s,l),m=c[0].length;for(p=0;m>p;++p)for(u.call(n,c[0][p],v=d[p],s[0][p][1]),g=1;h>g;++g)u.call(n,c[g][p],v+=s[g-1][p][1],s[g][p][1]);return o}var t=y,e=pu,r=vu,u=gu,i=fu,a=hu;return n.values=function(e){return arguments.length?(t=e,n):t},n.order=function(t){return arguments.length?(e="function"==typeof t?t:bl.get(t)||pu,n):e},n.offset=function(t){return arguments.length?(r="function"==typeof t?t:_l.get(t)||vu,n):r},n.x=function(t){return arguments.length?(i=t,n):i},n.y=function(t){return arguments.length?(a=t,n):a},n.out=function(t){return arguments.length?(u=t,n):u},n};var bl=oa.map({"inside-out":function(n){var t,e,r=n.length,u=n.map(du),i=n.map(mu),a=oa.range(r).sort(function(n,t){return u[n]-u[t]}),o=0,l=0,c=[],s=[];for(t=0;r>t;++t)e=a[t],l>o?(o+=i[e],c.push(e)):(l+=i[e],s.push(e));return s.reverse().concat(c)},reverse:function(n){return oa.range(n.length).reverse()},"default":pu}),_l=oa.map({silhouette:function(n){var t,e,r,u=n.length,i=n[0].length,a=[],o=0,l=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];r>o&&(o=r),a.push(r)}for(e=0;i>e;++e)l[e]=(o-a[e])/2;return l},wiggle:function(n){var t,e,r,u,i,a,o,l,c,s=n.length,f=n[0],h=f.length,g=[];for(g[0]=l=c=0,e=1;h>e;++e){for(t=0,u=0;s>t;++t)u+=n[t][e][1];for(t=0,i=0,o=f[e][0]-f[e-1][0];s>t;++t){for(r=0,a=(n[t][e][1]-n[t][e-1][1])/(2*o);t>r;++r)a+=(n[r][e][1]-n[r][e-1][1])/o;i+=a*n[t][e][1]}g[e]=l-=u?i/u*o:0,c>l&&(c=l)}for(e=0;h>e;++e)g[e]-=c;return g},expand:function(n){var t,e,r,u=n.length,i=n[0].length,a=1/u,o=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];if(r)for(t=0;u>t;t++)n[t][e][1]/=r;else for(t=0;u>t;t++)n[t][e][1]=a}for(e=0;i>e;++e)o[e]=0;return o},zero:vu});oa.layout.histogram=function(){function n(n,i){for(var a,o,l=[],c=n.map(e,this),s=r.call(this,c,i),f=u.call(this,s,c,i),i=-1,h=c.length,g=f.length-1,p=t?1:1/h;++i0)for(i=-1;++i=s[0]&&o<=s[1]&&(a=l[oa.bisect(f,o,1,g)-1],a.y+=p,a.push(n[i]));return l}var t=!0,e=Number,r=bu,u=Mu;return n.value=function(t){return arguments.length?(e=t,n):e},n.range=function(t){return arguments.length?(r=En(t),n):r},n.bins=function(t){return arguments.length?(u="number"==typeof t?function(n){return xu(n,t)}:En(t),n):u},n.frequency=function(e){return arguments.length?(t=!!e,n):t},n},oa.layout.pack=function(){function n(n,i){var a=e.call(this,n,i),o=a[0],l=u[0],c=u[1],s=null==t?Math.sqrt:"function"==typeof t?t:function(){return t};if(o.x=o.y=0,au(o,function(n){n.r=+s(n.value)}),au(o,Nu),r){var f=r*(t?1:Math.max(2*o.r/l,2*o.r/c))/2;au(o,function(n){n.r+=f}),au(o,Nu),au(o,function(n){n.r-=f})}return Cu(o,l/2,c/2,t?1:1/Math.max(2*o.r/l,2*o.r/c)),a}var t,e=oa.layout.hierarchy().sort(_u),r=0,u=[1,1];return n.size=function(t){return arguments.length?(u=t,n):u},n.radius=function(e){return arguments.length?(t=null==e||"function"==typeof e?e:+e,n):t},n.padding=function(t){return arguments.length?(r=+t,n):r},uu(n,e)},oa.layout.tree=function(){function n(n,u){var s=a.call(this,n,u),f=s[0],h=t(f);if(au(h,e),h.parent.m=-h.z,iu(h,r),c)iu(f,i);else{var g=f,p=f,v=f;iu(f,function(n){n.xp.x&&(p=n),n.depth>v.depth&&(v=n)});var d=o(g,p)/2-g.x,m=l[0]/(p.x+o(p,g)/2+d),y=l[1]/(v.depth||1);iu(f,function(n){n.x=(n.x+d)*m,n.y=n.depth*y})}return s}function t(n){for(var t,e={A:null,children:[n]},r=[e];null!=(t=r.pop());)for(var u,i=t.children,a=0,o=i.length;o>a;++a)r.push((i[a]=u={_:i[a],parent:t,children:(u=i[a].children)&&u.slice()||[],A:null,a:null,z:0,m:0,c:0,s:0,t:null,i:a}).a=u);return e.children[0]}function e(n){var t=n.children,e=n.parent.children,r=n.i?e[n.i-1]:null;if(t.length){Du(n);var i=(t[0].z+t[t.length-1].z)/2;r?(n.z=r.z+o(n._,r._),n.m=n.z-i):n.z=i}else r&&(n.z=r.z+o(n._,r._));n.parent.A=u(n,r,n.parent.A||e[0])}function r(n){n._.x=n.z+n.parent.m,n.m+=n.parent.m}function u(n,t,e){if(t){for(var r,u=n,i=n,a=t,l=u.parent.children[0],c=u.m,s=i.m,f=a.m,h=l.m;a=Tu(a),u=qu(u),a&&u;)l=qu(l),i=Tu(i),i.a=n,r=a.z+f-u.z-c+o(a._,u._),r>0&&(Ru(Pu(a,n,e),n,r),c+=r,s+=r),f+=a.m,c+=u.m,h+=l.m,s+=i.m;a&&!Tu(i)&&(i.t=a,i.m+=f-s),u&&!qu(l)&&(l.t=u,l.m+=c-h,e=n)}return e}function i(n){n.x*=l[0],n.y=n.depth*l[1]}var a=oa.layout.hierarchy().sort(null).value(null),o=Lu,l=[1,1],c=null;return n.separation=function(t){return arguments.length?(o=t,n):o},n.size=function(t){return arguments.length?(c=null==(l=t)?i:null,n):c?null:l},n.nodeSize=function(t){return arguments.length?(c=null==(l=t)?null:i,n):c?l:null},uu(n,a)},oa.layout.cluster=function(){function n(n,i){var a,o=t.call(this,n,i),l=o[0],c=0;au(l,function(n){var t=n.children;t&&t.length?(n.x=Uu(t),n.y=ju(t)):(n.x=a?c+=e(n,a):0,n.y=0,a=n)});var s=Fu(l),f=Hu(l),h=s.x-e(s,f)/2,g=f.x+e(f,s)/2;return au(l,u?function(n){n.x=(n.x-l.x)*r[0],n.y=(l.y-n.y)*r[1]}:function(n){n.x=(n.x-h)/(g-h)*r[0],n.y=(1-(l.y?n.y/l.y:1))*r[1]}),o}var t=oa.layout.hierarchy().sort(null).value(null),e=Lu,r=[1,1],u=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(u=null==(r=t),n):u?null:r},n.nodeSize=function(t){return arguments.length?(u=null!=(r=t),n):u?r:null},uu(n,t)},oa.layout.treemap=function(){function n(n,t){for(var e,r,u=-1,i=n.length;++ut?0:t),e.area=isNaN(r)||0>=r?0:r}function t(e){var i=e.children;if(i&&i.length){var a,o,l,c=f(e),s=[],h=i.slice(),p=1/0,v="slice"===g?c.dx:"dice"===g?c.dy:"slice-dice"===g?1&e.depth?c.dy:c.dx:Math.min(c.dx,c.dy);for(n(h,c.dx*c.dy/e.value),s.area=0;(l=h.length)>0;)s.push(a=h[l-1]),s.area+=a.area,"squarify"!==g||(o=r(s,v))<=p?(h.pop(),p=o):(s.area-=s.pop().area,u(s,v,c,!1),v=Math.min(c.dx,c.dy),s.length=s.area=0,p=1/0);s.length&&(u(s,v,c,!0),s.length=s.area=0),i.forEach(t)}}function e(t){var r=t.children;if(r&&r.length){var i,a=f(t),o=r.slice(),l=[];for(n(o,a.dx*a.dy/t.value),l.area=0;i=o.pop();)l.push(i),l.area+=i.area,null!=i.z&&(u(l,i.z?a.dx:a.dy,a,!o.length),l.length=l.area=0);r.forEach(e)}}function r(n,t){for(var e,r=n.area,u=0,i=1/0,a=-1,o=n.length;++ae&&(i=e),e>u&&(u=e));return r*=r,t*=t,r?Math.max(t*u*p/r,r/(t*i*p)):1/0}function u(n,t,e,r){var u,i=-1,a=n.length,o=e.x,c=e.y,s=t?l(n.area/t):0; +if(t==e.dx){for((r||s>e.dy)&&(s=e.dy);++ie.dx)&&(s=e.dx);++ie&&(t=1),1>e&&(n=0),function(){var e,r,u;do e=2*Math.random()-1,r=2*Math.random()-1,u=e*e+r*r;while(!u||u>1);return n+t*e*Math.sqrt(-2*Math.log(u)/u)}},logNormal:function(){var n=oa.random.normal.apply(oa,arguments);return function(){return Math.exp(n())}},bates:function(n){var t=oa.random.irwinHall(n);return function(){return t()/n}},irwinHall:function(n){return function(){for(var t=0,e=0;n>e;e++)t+=Math.random();return t}}},oa.scale={};var wl={floor:y,ceil:y};oa.scale.linear=function(){return Wu([0,1],[0,1],Mr,!1)};var Sl={s:1,g:1,p:1,r:1,e:1};oa.scale.log=function(){return ri(oa.scale.linear().domain([0,1]),10,!0,[1,10])};var kl=oa.format(".0e"),Nl={floor:function(n){return-Math.ceil(-n)},ceil:function(n){return-Math.floor(-n)}};oa.scale.pow=function(){return ui(oa.scale.linear(),1,[0,1])},oa.scale.sqrt=function(){return oa.scale.pow().exponent(.5)},oa.scale.ordinal=function(){return ai([],{t:"range",a:[[]]})},oa.scale.category10=function(){return oa.scale.ordinal().range(El)},oa.scale.category20=function(){return oa.scale.ordinal().range(Al)},oa.scale.category20b=function(){return oa.scale.ordinal().range(Cl)},oa.scale.category20c=function(){return oa.scale.ordinal().range(zl)};var El=[2062260,16744206,2924588,14034728,9725885,9197131,14907330,8355711,12369186,1556175].map(xn),Al=[2062260,11454440,16744206,16759672,2924588,10018698,14034728,16750742,9725885,12955861,9197131,12885140,14907330,16234194,8355711,13092807,12369186,14408589,1556175,10410725].map(xn),Cl=[3750777,5395619,7040719,10264286,6519097,9216594,11915115,13556636,9202993,12426809,15186514,15190932,8666169,11356490,14049643,15177372,8077683,10834324,13528509,14589654].map(xn),zl=[3244733,7057110,10406625,13032431,15095053,16616764,16625259,16634018,3253076,7652470,10607003,13101504,7695281,10394312,12369372,14342891,6513507,9868950,12434877,14277081].map(xn);oa.scale.quantile=function(){return oi([],[])},oa.scale.quantize=function(){return li(0,1,[0,1])},oa.scale.threshold=function(){return ci([.5],[0,1])},oa.scale.identity=function(){return si([0,1])},oa.svg={},oa.svg.arc=function(){function n(){var n=Math.max(0,+e.apply(this,arguments)),c=Math.max(0,+r.apply(this,arguments)),s=a.apply(this,arguments)-Ha,f=o.apply(this,arguments)-Ha,h=Math.abs(f-s),g=s>f?0:1;if(n>c&&(p=c,c=n,n=p),h>=Fa)return t(c,g)+(n?t(n,1-g):"")+"Z";var p,v,d,m,y,M,x,b,_,w,S,k,N=0,E=0,A=[];if((m=(+l.apply(this,arguments)||0)/2)&&(d=i===Ll?Math.sqrt(n*n+c*c):+i.apply(this,arguments),g||(E*=-1),c&&(E=tn(d/c*Math.sin(m))),n&&(N=tn(d/n*Math.sin(m)))),c){y=c*Math.cos(s+E),M=c*Math.sin(s+E),x=c*Math.cos(f-E),b=c*Math.sin(f-E);var C=Math.abs(f-s-2*E)<=ja?0:1;if(E&&mi(y,M,x,b)===g^C){var z=(s+f)/2;y=c*Math.cos(z),M=c*Math.sin(z),x=b=null}}else y=M=0;if(n){_=n*Math.cos(f-N),w=n*Math.sin(f-N),S=n*Math.cos(s+N),k=n*Math.sin(s+N);var L=Math.abs(s-f+2*N)<=ja?0:1;if(N&&mi(_,w,S,k)===1-g^L){var q=(s+f)/2;_=n*Math.cos(q),w=n*Math.sin(q),S=k=null}}else _=w=0;if(h>Da&&(p=Math.min(Math.abs(c-n)/2,+u.apply(this,arguments)))>.001){v=c>n^g?0:1;var T=p,R=p;if(ja>h){var D=null==S?[_,w]:null==x?[y,M]:Re([y,M],[S,k],[x,b],[_,w]),P=y-D[0],j=M-D[1],U=x-D[0],F=b-D[1],H=1/Math.sin(Math.acos((P*U+j*F)/(Math.sqrt(P*P+j*j)*Math.sqrt(U*U+F*F)))/2),O=Math.sqrt(D[0]*D[0]+D[1]*D[1]);R=Math.min(p,(n-O)/(H-1)),T=Math.min(p,(c-O)/(H+1))}if(null!=x){var I=yi(null==S?[_,w]:[S,k],[y,M],c,T,g),Y=yi([x,b],[_,w],c,T,g);p===T?A.push("M",I[0],"A",T,",",T," 0 0,",v," ",I[1],"A",c,",",c," 0 ",1-g^mi(I[1][0],I[1][1],Y[1][0],Y[1][1]),",",g," ",Y[1],"A",T,",",T," 0 0,",v," ",Y[0]):A.push("M",I[0],"A",T,",",T," 0 1,",v," ",Y[0])}else A.push("M",y,",",M);if(null!=S){var Z=yi([y,M],[S,k],n,-R,g),V=yi([_,w],null==x?[y,M]:[x,b],n,-R,g);p===R?A.push("L",V[0],"A",R,",",R," 0 0,",v," ",V[1],"A",n,",",n," 0 ",g^mi(V[1][0],V[1][1],Z[1][0],Z[1][1]),",",1-g," ",Z[1],"A",R,",",R," 0 0,",v," ",Z[0]):A.push("L",V[0],"A",R,",",R," 0 0,",v," ",Z[0])}else A.push("L",_,",",w)}else A.push("M",y,",",M),null!=x&&A.push("A",c,",",c," 0 ",C,",",g," ",x,",",b),A.push("L",_,",",w),null!=S&&A.push("A",n,",",n," 0 ",L,",",1-g," ",S,",",k);return A.push("Z"),A.join("")}function t(n,t){return"M0,"+n+"A"+n+","+n+" 0 1,"+t+" 0,"+-n+"A"+n+","+n+" 0 1,"+t+" 0,"+n}var e=hi,r=gi,u=fi,i=Ll,a=pi,o=vi,l=di;return n.innerRadius=function(t){return arguments.length?(e=En(t),n):e},n.outerRadius=function(t){return arguments.length?(r=En(t),n):r},n.cornerRadius=function(t){return arguments.length?(u=En(t),n):u},n.padRadius=function(t){return arguments.length?(i=t==Ll?Ll:En(t),n):i},n.startAngle=function(t){return arguments.length?(a=En(t),n):a},n.endAngle=function(t){return arguments.length?(o=En(t),n):o},n.padAngle=function(t){return arguments.length?(l=En(t),n):l},n.centroid=function(){var n=(+e.apply(this,arguments)+ +r.apply(this,arguments))/2,t=(+a.apply(this,arguments)+ +o.apply(this,arguments))/2-Ha;return[Math.cos(t)*n,Math.sin(t)*n]},n};var Ll="auto";oa.svg.line=function(){return Mi(y)};var ql=oa.map({linear:xi,"linear-closed":bi,step:_i,"step-before":wi,"step-after":Si,basis:zi,"basis-open":Li,"basis-closed":qi,bundle:Ti,cardinal:Ei,"cardinal-open":ki,"cardinal-closed":Ni,monotone:Fi});ql.forEach(function(n,t){t.key=n,t.closed=/-closed$/.test(n)});var Tl=[0,2/3,1/3,0],Rl=[0,1/3,2/3,0],Dl=[0,1/6,2/3,1/6];oa.svg.line.radial=function(){var n=Mi(Hi);return n.radius=n.x,delete n.x,n.angle=n.y,delete n.y,n},wi.reverse=Si,Si.reverse=wi,oa.svg.area=function(){return Oi(y)},oa.svg.area.radial=function(){var n=Oi(Hi);return n.radius=n.x,delete n.x,n.innerRadius=n.x0,delete n.x0,n.outerRadius=n.x1,delete n.x1,n.angle=n.y,delete n.y,n.startAngle=n.y0,delete n.y0,n.endAngle=n.y1,delete n.y1,n},oa.svg.chord=function(){function n(n,o){var l=t(this,i,n,o),c=t(this,a,n,o);return"M"+l.p0+r(l.r,l.p1,l.a1-l.a0)+(e(l,c)?u(l.r,l.p1,l.r,l.p0):u(l.r,l.p1,c.r,c.p0)+r(c.r,c.p1,c.a1-c.a0)+u(c.r,c.p1,l.r,l.p0))+"Z"}function t(n,t,e,r){var u=t.call(n,e,r),i=o.call(n,u,r),a=l.call(n,u,r)-Ha,s=c.call(n,u,r)-Ha;return{r:i,a0:a,a1:s,p0:[i*Math.cos(a),i*Math.sin(a)],p1:[i*Math.cos(s),i*Math.sin(s)]}}function e(n,t){return n.a0==t.a0&&n.a1==t.a1}function r(n,t,e){return"A"+n+","+n+" 0 "+ +(e>ja)+",1 "+t}function u(n,t,e,r){return"Q 0,0 "+r}var i=Me,a=xe,o=Ii,l=pi,c=vi;return n.radius=function(t){return arguments.length?(o=En(t),n):o},n.source=function(t){return arguments.length?(i=En(t),n):i},n.target=function(t){return arguments.length?(a=En(t),n):a},n.startAngle=function(t){return arguments.length?(l=En(t),n):l},n.endAngle=function(t){return arguments.length?(c=En(t),n):c},n},oa.svg.diagonal=function(){function n(n,u){var i=t.call(this,n,u),a=e.call(this,n,u),o=(i.y+a.y)/2,l=[i,{x:i.x,y:o},{x:a.x,y:o},a];return l=l.map(r),"M"+l[0]+"C"+l[1]+" "+l[2]+" "+l[3]}var t=Me,e=xe,r=Yi;return n.source=function(e){return arguments.length?(t=En(e),n):t},n.target=function(t){return arguments.length?(e=En(t),n):e},n.projection=function(t){return arguments.length?(r=t,n):r},n},oa.svg.diagonal.radial=function(){var n=oa.svg.diagonal(),t=Yi,e=n.projection;return n.projection=function(n){return arguments.length?e(Zi(t=n)):t},n},oa.svg.symbol=function(){function n(n,r){return(Pl.get(t.call(this,n,r))||$i)(e.call(this,n,r))}var t=Xi,e=Vi;return n.type=function(e){return arguments.length?(t=En(e),n):t},n.size=function(t){return arguments.length?(e=En(t),n):e},n};var Pl=oa.map({circle:$i,cross:function(n){var t=Math.sqrt(n/5)/2;return"M"+-3*t+","+-t+"H"+-t+"V"+-3*t+"H"+t+"V"+-t+"H"+3*t+"V"+t+"H"+t+"V"+3*t+"H"+-t+"V"+t+"H"+-3*t+"Z"},diamond:function(n){var t=Math.sqrt(n/(2*Ul)),e=t*Ul;return"M0,"+-t+"L"+e+",0 0,"+t+" "+-e+",0Z"},square:function(n){var t=Math.sqrt(n)/2;return"M"+-t+","+-t+"L"+t+","+-t+" "+t+","+t+" "+-t+","+t+"Z"},"triangle-down":function(n){var t=Math.sqrt(n/jl),e=t*jl/2;return"M0,"+e+"L"+t+","+-e+" "+-t+","+-e+"Z"},"triangle-up":function(n){var t=Math.sqrt(n/jl),e=t*jl/2;return"M0,"+-e+"L"+t+","+e+" "+-t+","+e+"Z"}});oa.svg.symbolTypes=Pl.keys();var jl=Math.sqrt(3),Ul=Math.tan(30*Oa);Aa.transition=function(n){for(var t,e,r=Fl||++Yl,u=Ki(n),i=[],a=Hl||{time:Date.now(),ease:Nr,delay:0,duration:250},o=-1,l=this.length;++oi;i++){u.push(t=[]);for(var e=this[i],o=0,l=e.length;l>o;o++)(r=e[o])&&n.call(r,r.__data__,o,i)&&t.push(r)}return Wi(u,this.namespace,this.id)},Il.tween=function(n,t){var e=this.id,r=this.namespace;return arguments.length<2?this.node()[r][e].tween.get(n):Y(this,null==t?function(t){t[r][e].tween.remove(n)}:function(u){u[r][e].tween.set(n,t)})},Il.attr=function(n,t){function e(){this.removeAttribute(o)}function r(){this.removeAttributeNS(o.space,o.local)}function u(n){return null==n?e:(n+="",function(){var t,e=this.getAttribute(o);return e!==n&&(t=a(e,n),function(n){this.setAttribute(o,t(n))})})}function i(n){return null==n?r:(n+="",function(){var t,e=this.getAttributeNS(o.space,o.local);return e!==n&&(t=a(e,n),function(n){this.setAttributeNS(o.space,o.local,t(n))})})}if(arguments.length<2){for(t in n)this.attr(t,n[t]);return this}var a="transform"==n?$r:Mr,o=oa.ns.qualify(n);return Ji(this,"attr."+n,t,o.local?i:u)},Il.attrTween=function(n,t){function e(n,e){var r=t.call(this,n,e,this.getAttribute(u));return r&&function(n){this.setAttribute(u,r(n))}}function r(n,e){var r=t.call(this,n,e,this.getAttributeNS(u.space,u.local));return r&&function(n){this.setAttributeNS(u.space,u.local,r(n))}}var u=oa.ns.qualify(n);return this.tween("attr."+n,u.local?r:e)},Il.style=function(n,e,r){function u(){this.style.removeProperty(n)}function i(e){return null==e?u:(e+="",function(){var u,i=t(this).getComputedStyle(this,null).getPropertyValue(n);return i!==e&&(u=Mr(i,e),function(t){this.style.setProperty(n,u(t),r)})})}var a=arguments.length;if(3>a){if("string"!=typeof n){2>a&&(e="");for(r in n)this.style(r,n[r],e);return this}r=""}return Ji(this,"style."+n,e,i)},Il.styleTween=function(n,e,r){function u(u,i){var a=e.call(this,u,i,t(this).getComputedStyle(this,null).getPropertyValue(n));return a&&function(t){this.style.setProperty(n,a(t),r)}}return arguments.length<3&&(r=""),this.tween("style."+n,u)},Il.text=function(n){return Ji(this,"text",n,Gi)},Il.remove=function(){var n=this.namespace;return this.each("end.transition",function(){var t;this[n].count<2&&(t=this.parentNode)&&t.removeChild(this)})},Il.ease=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].ease:("function"!=typeof n&&(n=oa.ease.apply(oa,arguments)),Y(this,function(r){r[e][t].ease=n}))},Il.delay=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].delay:Y(this,"function"==typeof n?function(r,u,i){r[e][t].delay=+n.call(r,r.__data__,u,i)}:(n=+n,function(r){r[e][t].delay=n}))},Il.duration=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].duration:Y(this,"function"==typeof n?function(r,u,i){r[e][t].duration=Math.max(1,n.call(r,r.__data__,u,i))}:(n=Math.max(1,n),function(r){r[e][t].duration=n}))},Il.each=function(n,t){var e=this.id,r=this.namespace;if(arguments.length<2){var u=Hl,i=Fl;try{Fl=e,Y(this,function(t,u,i){Hl=t[r][e],n.call(t,t.__data__,u,i)})}finally{Hl=u,Fl=i}}else Y(this,function(u){var i=u[r][e];(i.event||(i.event=oa.dispatch("start","end","interrupt"))).on(n,t)});return this},Il.transition=function(){for(var n,t,e,r,u=this.id,i=++Yl,a=this.namespace,o=[],l=0,c=this.length;c>l;l++){o.push(n=[]);for(var t=this[l],s=0,f=t.length;f>s;s++)(e=t[s])&&(r=e[a][u],Qi(e,s,a,i,{time:r.time,ease:r.ease,delay:r.delay+r.duration,duration:r.duration})),n.push(e)}return Wi(o,a,i)},oa.svg.axis=function(){function n(n){n.each(function(){var n,c=oa.select(this),s=this.__chart__||e,f=this.__chart__=e.copy(),h=null==l?f.ticks?f.ticks.apply(f,o):f.domain():l,g=null==t?f.tickFormat?f.tickFormat.apply(f,o):y:t,p=c.selectAll(".tick").data(h,f),v=p.enter().insert("g",".domain").attr("class","tick").style("opacity",Da),d=oa.transition(p.exit()).style("opacity",Da).remove(),m=oa.transition(p.order()).style("opacity",1),M=Math.max(u,0)+a,x=Zu(f),b=c.selectAll(".domain").data([0]),_=(b.enter().append("path").attr("class","domain"),oa.transition(b));v.append("line"),v.append("text");var w,S,k,N,E=v.select("line"),A=m.select("line"),C=p.select("text").text(g),z=v.select("text"),L=m.select("text"),q="top"===r||"left"===r?-1:1;if("bottom"===r||"top"===r?(n=na,w="x",k="y",S="x2",N="y2",C.attr("dy",0>q?"0em":".71em").style("text-anchor","middle"),_.attr("d","M"+x[0]+","+q*i+"V0H"+x[1]+"V"+q*i)):(n=ta,w="y",k="x",S="y2",N="x2",C.attr("dy",".32em").style("text-anchor",0>q?"end":"start"),_.attr("d","M"+q*i+","+x[0]+"H0V"+x[1]+"H"+q*i)),E.attr(N,q*u),z.attr(k,q*M),A.attr(S,0).attr(N,q*u),L.attr(w,0).attr(k,q*M),f.rangeBand){var T=f,R=T.rangeBand()/2;s=f=function(n){return T(n)+R}}else s.rangeBand?s=f:d.call(n,f,s);v.call(n,s,f),m.call(n,f,f)})}var t,e=oa.scale.linear(),r=Zl,u=6,i=6,a=3,o=[10],l=null;return n.scale=function(t){return arguments.length?(e=t,n):e},n.orient=function(t){return arguments.length?(r=t in Vl?t+"":Zl,n):r},n.ticks=function(){return arguments.length?(o=ca(arguments),n):o},n.tickValues=function(t){return arguments.length?(l=t,n):l},n.tickFormat=function(e){return arguments.length?(t=e,n):t},n.tickSize=function(t){var e=arguments.length;return e?(u=+t,i=+arguments[e-1],n):u},n.innerTickSize=function(t){return arguments.length?(u=+t,n):u},n.outerTickSize=function(t){return arguments.length?(i=+t,n):i},n.tickPadding=function(t){return arguments.length?(a=+t,n):a},n.tickSubdivide=function(){return arguments.length&&n},n};var Zl="bottom",Vl={top:1,right:1,bottom:1,left:1};oa.svg.brush=function(){function n(t){t.each(function(){var t=oa.select(this).style("pointer-events","all").style("-webkit-tap-highlight-color","rgba(0,0,0,0)").on("mousedown.brush",i).on("touchstart.brush",i),a=t.selectAll(".background").data([0]);a.enter().append("rect").attr("class","background").style("visibility","hidden").style("cursor","crosshair"),t.selectAll(".extent").data([0]).enter().append("rect").attr("class","extent").style("cursor","move");var o=t.selectAll(".resize").data(v,y);o.exit().remove(),o.enter().append("g").attr("class",function(n){return"resize "+n}).style("cursor",function(n){return Xl[n]}).append("rect").attr("x",function(n){return/[ew]$/.test(n)?-3:null}).attr("y",function(n){return/^[ns]/.test(n)?-3:null}).attr("width",6).attr("height",6).style("visibility","hidden"),o.style("display",n.empty()?"none":null);var l,f=oa.transition(t),h=oa.transition(a);c&&(l=Zu(c),h.attr("x",l[0]).attr("width",l[1]-l[0]),r(f)),s&&(l=Zu(s),h.attr("y",l[0]).attr("height",l[1]-l[0]),u(f)),e(f)})}function e(n){n.selectAll(".resize").attr("transform",function(n){return"translate("+f[+/e$/.test(n)]+","+h[+/^s/.test(n)]+")"})}function r(n){n.select(".extent").attr("x",f[0]),n.selectAll(".extent,.n>rect,.s>rect").attr("width",f[1]-f[0])}function u(n){n.select(".extent").attr("y",h[0]),n.selectAll(".extent,.e>rect,.w>rect").attr("height",h[1]-h[0])}function i(){function i(){32==oa.event.keyCode&&(C||(M=null,L[0]-=f[1],L[1]-=h[1],C=2),S())}function v(){32==oa.event.keyCode&&2==C&&(L[0]+=f[1],L[1]+=h[1],C=0,S())}function d(){var n=oa.mouse(b),t=!1;x&&(n[0]+=x[0],n[1]+=x[1]),C||(oa.event.altKey?(M||(M=[(f[0]+f[1])/2,(h[0]+h[1])/2]),L[0]=f[+(n[0]s?(u=r,r=s):u=s),v[0]!=r||v[1]!=u?(e?o=null:a=null,v[0]=r,v[1]=u,!0):void 0}function y(){d(),k.style("pointer-events","all").selectAll(".resize").style("display",n.empty()?"none":null),oa.select("body").style("cursor",null),q.on("mousemove.brush",null).on("mouseup.brush",null).on("touchmove.brush",null).on("touchend.brush",null).on("keydown.brush",null).on("keyup.brush",null),z(),w({type:"brushend"})}var M,x,b=this,_=oa.select(oa.event.target),w=l.of(b,arguments),k=oa.select(b),N=_.datum(),E=!/^(n|s)$/.test(N)&&c,A=!/^(e|w)$/.test(N)&&s,C=_.classed("extent"),z=W(b),L=oa.mouse(b),q=oa.select(t(b)).on("keydown.brush",i).on("keyup.brush",v);if(oa.event.changedTouches?q.on("touchmove.brush",d).on("touchend.brush",y):q.on("mousemove.brush",d).on("mouseup.brush",y),k.interrupt().selectAll("*").interrupt(),C)L[0]=f[0]-L[0],L[1]=h[0]-L[1];else if(N){var T=+/w$/.test(N),R=+/^n/.test(N);x=[f[1-T]-L[0],h[1-R]-L[1]],L[0]=f[T],L[1]=h[R]}else oa.event.altKey&&(M=L.slice());k.style("pointer-events","none").selectAll(".resize").style("display",null),oa.select("body").style("cursor",_.style("cursor")),w({type:"brushstart"}),d()}var a,o,l=N(n,"brushstart","brush","brushend"),c=null,s=null,f=[0,0],h=[0,0],g=!0,p=!0,v=$l[0];return n.event=function(n){n.each(function(){var n=l.of(this,arguments),t={x:f,y:h,i:a,j:o},e=this.__chart__||t;this.__chart__=t,Fl?oa.select(this).transition().each("start.brush",function(){a=e.i,o=e.j,f=e.x,h=e.y,n({type:"brushstart"})}).tween("brush:brush",function(){var e=xr(f,t.x),r=xr(h,t.y);return a=o=null,function(u){f=t.x=e(u),h=t.y=r(u),n({type:"brush",mode:"resize"})}}).each("end.brush",function(){a=t.i,o=t.j,n({type:"brush",mode:"resize"}),n({type:"brushend"})}):(n({type:"brushstart"}),n({type:"brush",mode:"resize"}),n({type:"brushend"}))})},n.x=function(t){return arguments.length?(c=t,v=$l[!c<<1|!s],n):c},n.y=function(t){return arguments.length?(s=t,v=$l[!c<<1|!s],n):s},n.clamp=function(t){return arguments.length?(c&&s?(g=!!t[0],p=!!t[1]):c?g=!!t:s&&(p=!!t),n):c&&s?[g,p]:c?g:s?p:null},n.extent=function(t){var e,r,u,i,l;return arguments.length?(c&&(e=t[0],r=t[1],s&&(e=e[0],r=r[0]),a=[e,r],c.invert&&(e=c(e),r=c(r)),e>r&&(l=e,e=r,r=l),(e!=f[0]||r!=f[1])&&(f=[e,r])),s&&(u=t[0],i=t[1],c&&(u=u[1],i=i[1]),o=[u,i],s.invert&&(u=s(u),i=s(i)),u>i&&(l=u,u=i,i=l),(u!=h[0]||i!=h[1])&&(h=[u,i])),n):(c&&(a?(e=a[0],r=a[1]):(e=f[0],r=f[1],c.invert&&(e=c.invert(e),r=c.invert(r)),e>r&&(l=e,e=r,r=l))),s&&(o?(u=o[0],i=o[1]):(u=h[0],i=h[1],s.invert&&(u=s.invert(u),i=s.invert(i)),u>i&&(l=u,u=i,i=l))),c&&s?[[e,u],[r,i]]:c?[e,r]:s&&[u,i])},n.clear=function(){return n.empty()||(f=[0,0],h=[0,0],a=o=null),n},n.empty=function(){return!!c&&f[0]==f[1]||!!s&&h[0]==h[1]},oa.rebind(n,l,"on")};var Xl={n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},$l=[["n","e","s","w","nw","ne","se","sw"],["e","w"],["n","s"],[]],Bl=ho.format=Mo.timeFormat,Wl=Bl.utc,Jl=Wl("%Y-%m-%dT%H:%M:%S.%LZ");Bl.iso=Date.prototype.toISOString&&+new Date("2000-01-01T00:00:00.000Z")?ea:Jl,ea.parse=function(n){var t=new Date(n);return isNaN(t)?null:t},ea.toString=Jl.toString,ho.second=On(function(n){return new go(1e3*Math.floor(n/1e3))},function(n,t){n.setTime(n.getTime()+1e3*Math.floor(t))},function(n){return n.getSeconds()}),ho.seconds=ho.second.range,ho.seconds.utc=ho.second.utc.range,ho.minute=On(function(n){return new go(6e4*Math.floor(n/6e4))},function(n,t){n.setTime(n.getTime()+6e4*Math.floor(t))},function(n){return n.getMinutes()}),ho.minutes=ho.minute.range,ho.minutes.utc=ho.minute.utc.range,ho.hour=On(function(n){var t=n.getTimezoneOffset()/60;return new go(36e5*(Math.floor(n/36e5-t)+t))},function(n,t){n.setTime(n.getTime()+36e5*Math.floor(t))},function(n){return n.getHours()}),ho.hours=ho.hour.range,ho.hours.utc=ho.hour.utc.range,ho.month=On(function(n){return n=ho.day(n),n.setDate(1),n},function(n,t){n.setMonth(n.getMonth()+t)},function(n){return n.getMonth()}),ho.months=ho.month.range,ho.months.utc=ho.month.utc.range;var Gl=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],Kl=[[ho.second,1],[ho.second,5],[ho.second,15],[ho.second,30],[ho.minute,1],[ho.minute,5],[ho.minute,15],[ho.minute,30],[ho.hour,1],[ho.hour,3],[ho.hour,6],[ho.hour,12],[ho.day,1],[ho.day,2],[ho.week,1],[ho.month,1],[ho.month,3],[ho.year,1]],Ql=Bl.multi([[".%L",function(n){return n.getMilliseconds()}],[":%S",function(n){return n.getSeconds()}],["%I:%M",function(n){return n.getMinutes()}],["%I %p",function(n){return n.getHours()}],["%a %d",function(n){return n.getDay()&&1!=n.getDate()}],["%b %d",function(n){return 1!=n.getDate()}],["%B",function(n){return n.getMonth()}],["%Y",zt]]),nc={range:function(n,t,e){return oa.range(Math.ceil(n/e)*e,+t,e).map(ua)},floor:y,ceil:y};Kl.year=ho.year,ho.scale=function(){return ra(oa.scale.linear(),Kl,Ql)};var tc=Kl.map(function(n){return[n[0].utc,n[1]]}),ec=Wl.multi([[".%L",function(n){return n.getUTCMilliseconds()}],[":%S",function(n){return n.getUTCSeconds()}],["%I:%M",function(n){return n.getUTCMinutes()}],["%I %p",function(n){return n.getUTCHours()}],["%a %d",function(n){return n.getUTCDay()&&1!=n.getUTCDate()}],["%b %d",function(n){return 1!=n.getUTCDate()}],["%B",function(n){return n.getUTCMonth()}],["%Y",zt]]);tc.year=ho.year.utc,ho.scale.utc=function(){return ra(oa.scale.linear(),tc,ec)},oa.text=An(function(n){return n.responseText}),oa.json=function(n,t){return Cn(n,"application/json",ia,t)},oa.html=function(n,t){return Cn(n,"text/html",aa,t)},oa.xml=An(function(n){return n.responseXML}),"function"==typeof define&&define.amd?(this.d3=oa,define(oa)):"object"==typeof module&&module.exports?module.exports=oa:this.d3=oa}(); \ No newline at end of file diff --git a/visualisations/JsRoot460/scripts/dat.gui.min.js b/visualisations/JsRoot460/scripts/dat.gui.min.js new file mode 100644 index 0000000..8ea141a --- /dev/null +++ b/visualisations/JsRoot460/scripts/dat.gui.min.js @@ -0,0 +1,95 @@ +/** + * dat-gui JavaScript Controller Library + * http://code.google.com/p/dat-gui + * + * Copyright 2011 Data Arts Team, Google Creative Lab + * + * 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 + */ +var dat=dat||{};dat.gui=dat.gui||{};dat.utils=dat.utils||{};dat.controllers=dat.controllers||{};dat.dom=dat.dom||{};dat.color=dat.color||{};dat.utils.css=function(){return{load:function(f,a){a=a||document;var d=a.createElement("link");d.type="text/css";d.rel="stylesheet";d.href=f;a.getElementsByTagName("head")[0].appendChild(d)},inject:function(f,a){a=a||document;var d=document.createElement("style");d.type="text/css";d.innerHTML=f;a.getElementsByTagName("head")[0].appendChild(d)}}}(); +dat.utils.common=function(){var f=Array.prototype.forEach,a=Array.prototype.slice;return{BREAK:{},extend:function(d){this.each(a.call(arguments,1),function(a){for(var c in a)this.isUndefined(a[c])||(d[c]=a[c])},this);return d},defaults:function(d){this.each(a.call(arguments,1),function(a){for(var c in a)this.isUndefined(d[c])&&(d[c]=a[c])},this);return d},compose:function(){var d=a.call(arguments);return function(){for(var e=a.call(arguments),c=d.length-1;0<=c;c--)e=[d[c].apply(this,e)];return e[0]}}, +each:function(a,e,c){if(a)if(f&&a.forEach&&a.forEach===f)a.forEach(e,c);else if(a.length===a.length+0)for(var b=0,p=a.length;bthis.__max&&(a=this.__max);void 0!==this.__step&&0!=a%this.__step&&(a=Math.round(a/this.__step)*this.__step);return e.superclass.prototype.setValue.call(this,a)},min:function(a){this.__min=a;return this},max:function(a){this.__max=a;return this},step:function(a){this.__impliedStep=this.__step=a;this.__precision=d(a);return this}});return e}(dat.controllers.Controller,dat.utils.common); +dat.controllers.NumberControllerBox=function(f,a,d){var e=function(c,b,f){function q(){var a=parseFloat(n.__input.value);d.isNaN(a)||n.setValue(a)}function l(a){var b=u-a.clientY;n.setValue(n.getValue()+b*n.__impliedStep);u=a.clientY}function r(){a.unbind(window,"mousemove",l);a.unbind(window,"mouseup",r)}this.__truncationSuspended=!1;e.superclass.call(this,c,b,f);var n=this,u;this.__input=document.createElement("input");this.__input.setAttribute("type","text");a.bind(this.__input,"change",q);a.bind(this.__input, +"blur",function(){q();n.__onFinishChange&&n.__onFinishChange.call(n,n.getValue())});a.bind(this.__input,"mousedown",function(b){a.bind(window,"mousemove",l);a.bind(window,"mouseup",r);u=b.clientY});a.bind(this.__input,"keydown",function(a){13===a.keyCode&&(n.__truncationSuspended=!0,this.blur(),n.__truncationSuspended=!1)});this.updateDisplay();this.domElement.appendChild(this.__input)};e.superclass=f;d.extend(e.prototype,f.prototype,{updateDisplay:function(){var a=this.__input,b;if(this.__truncationSuspended)b= +this.getValue();else{b=this.getValue();var d=Math.pow(10,this.__precision);b=Math.round(b*d)/d}a.value=b;return e.superclass.prototype.updateDisplay.call(this)}});return e}(dat.controllers.NumberController,dat.dom.dom,dat.utils.common); +dat.controllers.NumberControllerSlider=function(f,a,d,e,c){function b(a,b,c,e,d){return e+(a-b)/(c-b)*(d-e)}var p=function(c,e,d,f,u){function A(c){c.preventDefault();var e=a.getOffset(k.__background),d=a.getWidth(k.__background);k.setValue(b(c.clientX,e.left,e.left+d,k.__min,k.__max));return!1}function g(){a.unbind(window,"mousemove",A);a.unbind(window,"mouseup",g);k.__onFinishChange&&k.__onFinishChange.call(k,k.getValue())}p.superclass.call(this,c,e,{min:d,max:f,step:u});var k=this;this.__background= +document.createElement("div");this.__foreground=document.createElement("div");a.bind(this.__background,"mousedown",function(b){a.bind(window,"mousemove",A);a.bind(window,"mouseup",g);A(b)});a.addClass(this.__background,"slider");a.addClass(this.__foreground,"slider-fg");this.updateDisplay();this.__background.appendChild(this.__foreground);this.domElement.appendChild(this.__background)};p.superclass=f;p.useDefaultStyles=function(){d.inject(c)};e.extend(p.prototype,f.prototype,{updateDisplay:function(){var a= +(this.getValue()-this.__min)/(this.__max-this.__min);this.__foreground.style.width=100*a+"%";return p.superclass.prototype.updateDisplay.call(this)}});return p}(dat.controllers.NumberController,dat.dom.dom,dat.utils.css,dat.utils.common,"/**\n * dat-gui JavaScript Controller Library\n * http://code.google.com/p/dat-gui\n *\n * Copyright 2011 Data Arts Team, Google Creative Lab\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n */\n\n.slider {\n box-shadow: inset 0 2px 4px rgba(0,0,0,0.15);\n height: 1em;\n border-radius: 1em;\n background-color: #eee;\n padding: 0 0.5em;\n overflow: hidden;\n}\n\n.slider-fg {\n padding: 1px 0 2px 0;\n background-color: #aaa;\n height: 1em;\n margin-left: -0.5em;\n padding-right: 0.5em;\n border-radius: 1em 0 0 1em;\n}\n\n.slider-fg:after {\n display: inline-block;\n border-radius: 1em;\n background-color: #fff;\n border: 1px solid #aaa;\n content: '';\n float: right;\n margin-right: -1em;\n margin-top: -1px;\n height: 0.9em;\n width: 0.9em;\n}"); +dat.controllers.FunctionController=function(f,a,d){var e=function(c,b,d){e.superclass.call(this,c,b);var f=this;this.__button=document.createElement("div");this.__button.innerHTML=void 0===d?"Fire":d;a.bind(this.__button,"click",function(a){a.preventDefault();f.fire();return!1});a.addClass(this.__button,"button");this.domElement.appendChild(this.__button)};e.superclass=f;d.extend(e.prototype,f.prototype,{fire:function(){this.__onChange&&this.__onChange.call(this);this.getValue().call(this.object); +this.__onFinishChange&&this.__onFinishChange.call(this,this.getValue())}});return e}(dat.controllers.Controller,dat.dom.dom,dat.utils.common); +dat.controllers.BooleanController=function(f,a,d){var e=function(c,b){e.superclass.call(this,c,b);var d=this;this.__prev=this.getValue();this.__checkbox=document.createElement("input");this.__checkbox.setAttribute("type","checkbox");a.bind(this.__checkbox,"change",function(){d.setValue(!d.__prev)},!1);this.domElement.appendChild(this.__checkbox);this.updateDisplay()};e.superclass=f;d.extend(e.prototype,f.prototype,{setValue:function(a){a=e.superclass.prototype.setValue.call(this,a);this.__onFinishChange&& +this.__onFinishChange.call(this,this.getValue());this.__prev=this.getValue();return a},updateDisplay:function(){!0===this.getValue()?(this.__checkbox.setAttribute("checked","checked"),this.__checkbox.checked=!0):this.__checkbox.checked=!1;return e.superclass.prototype.updateDisplay.call(this)}});return e}(dat.controllers.Controller,dat.dom.dom,dat.utils.common); +dat.color.toString=function(f){return function(a){if(1==a.a||f.isUndefined(a.a)){for(a=a.hex.toString(16);6>a.length;)a="0"+a;return"#"+a}return"rgba("+Math.round(a.r)+","+Math.round(a.g)+","+Math.round(a.b)+","+a.a+")"}}(dat.utils.common); +dat.color.interpret=function(f,a){var d,e,c=[{litmus:a.isString,conversions:{THREE_CHAR_HEX:{read:function(a){a=a.match(/^#([A-F0-9])([A-F0-9])([A-F0-9])$/i);return null===a?!1:{space:"HEX",hex:parseInt("0x"+a[1].toString()+a[1].toString()+a[2].toString()+a[2].toString()+a[3].toString()+a[3].toString())}},write:f},SIX_CHAR_HEX:{read:function(a){a=a.match(/^#([A-F0-9]{6})$/i);return null===a?!1:{space:"HEX",hex:parseInt("0x"+a[1].toString())}},write:f},CSS_RGB:{read:function(a){a=a.match(/^rgb\(\s*(.+)\s*,\s*(.+)\s*,\s*(.+)\s*\)/); +return null===a?!1:{space:"RGB",r:parseFloat(a[1]),g:parseFloat(a[2]),b:parseFloat(a[3])}},write:f},CSS_RGBA:{read:function(a){a=a.match(/^rgba\(\s*(.+)\s*,\s*(.+)\s*,\s*(.+)\s*\,\s*(.+)\s*\)/);return null===a?!1:{space:"RGB",r:parseFloat(a[1]),g:parseFloat(a[2]),b:parseFloat(a[3]),a:parseFloat(a[4])}},write:f}}},{litmus:a.isNumber,conversions:{HEX:{read:function(a){return{space:"HEX",hex:a,conversionName:"HEX"}},write:function(a){return a.hex}}}},{litmus:a.isArray,conversions:{RGB_ARRAY:{read:function(a){return 3!= +a.length?!1:{space:"RGB",r:a[0],g:a[1],b:a[2]}},write:function(a){return[a.r,a.g,a.b]}},RGBA_ARRAY:{read:function(a){return 4!=a.length?!1:{space:"RGB",r:a[0],g:a[1],b:a[2],a:a[3]}},write:function(a){return[a.r,a.g,a.b,a.a]}}}},{litmus:a.isObject,conversions:{RGBA_OBJ:{read:function(b){return a.isNumber(b.r)&&a.isNumber(b.g)&&a.isNumber(b.b)&&a.isNumber(b.a)?{space:"RGB",r:b.r,g:b.g,b:b.b,a:b.a}:!1},write:function(a){return{r:a.r,g:a.g,b:a.b,a:a.a}}},RGB_OBJ:{read:function(b){return a.isNumber(b.r)&& +a.isNumber(b.g)&&a.isNumber(b.b)?{space:"RGB",r:b.r,g:b.g,b:b.b}:!1},write:function(a){return{r:a.r,g:a.g,b:a.b}}},HSVA_OBJ:{read:function(b){return a.isNumber(b.h)&&a.isNumber(b.s)&&a.isNumber(b.v)&&a.isNumber(b.a)?{space:"HSV",h:b.h,s:b.s,v:b.v,a:b.a}:!1},write:function(a){return{h:a.h,s:a.s,v:a.v,a:a.a}}},HSV_OBJ:{read:function(b){return a.isNumber(b.h)&&a.isNumber(b.s)&&a.isNumber(b.v)?{space:"HSV",h:b.h,s:b.s,v:b.v}:!1},write:function(a){return{h:a.h,s:a.s,v:a.v}}}}}];return function(){e=!1; +var b=1\n\n Here\'s the new load parameter for your GUI\'s constructor:\n\n \n\n
    \n\n Automatically save\n values to localStorage on exit.\n\n
    The values saved to localStorage will\n override those passed to dat.GUI\'s constructor. This makes it\n easier to work incrementally, but localStorage is fragile,\n and your friends may not see the same values you do.\n \n
    \n \n
    \n\n', +".dg {\n /** Clear list styles */\n /* Auto-place container */\n /* Auto-placed GUI's */\n /* Line items that don't contain folders. */\n /** Folder names */\n /** Hides closed items */\n /** Controller row */\n /** Name-half (left) */\n /** Controller-half (right) */\n /** Controller placement */\n /** Shorter number boxes when slider is present. */\n /** Ensure the entire boolean and function row shows a hand */ }\n .dg ul {\n list-style: none;\n margin: 0;\n padding: 0;\n width: 100%;\n clear: both; }\n .dg.ac {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n height: 0;\n z-index: 0; }\n .dg:not(.ac) .main {\n /** Exclude mains in ac so that we don't hide close button */\n overflow: hidden; }\n .dg.main {\n -webkit-transition: opacity 0.1s linear;\n -o-transition: opacity 0.1s linear;\n -moz-transition: opacity 0.1s linear;\n transition: opacity 0.1s linear; }\n .dg.main.taller-than-window {\n overflow-y: auto; }\n .dg.main.taller-than-window .close-button {\n opacity: 1;\n /* TODO, these are style notes */\n margin-top: -1px;\n border-top: 1px solid #2c2c2c; }\n .dg.main ul.closed .close-button {\n opacity: 1 !important; }\n .dg.main:hover .close-button,\n .dg.main .close-button.drag {\n opacity: 1; }\n .dg.main .close-button {\n /*opacity: 0;*/\n -webkit-transition: opacity 0.1s linear;\n -o-transition: opacity 0.1s linear;\n -moz-transition: opacity 0.1s linear;\n transition: opacity 0.1s linear;\n border: 0;\n position: absolute;\n line-height: 19px;\n height: 20px;\n /* TODO, these are style notes */\n cursor: pointer;\n text-align: center;\n background-color: #000; }\n .dg.main .close-button:hover {\n background-color: #111; }\n .dg.a {\n float: right;\n margin-right: 15px;\n overflow-x: hidden; }\n .dg.a.has-save > ul {\n margin-top: 27px; }\n .dg.a.has-save > ul.closed {\n margin-top: 0; }\n .dg.a .save-row {\n position: fixed;\n top: 0;\n z-index: 1002; }\n .dg li {\n -webkit-transition: height 0.1s ease-out;\n -o-transition: height 0.1s ease-out;\n -moz-transition: height 0.1s ease-out;\n transition: height 0.1s ease-out; }\n .dg li:not(.folder) {\n cursor: auto;\n height: 27px;\n line-height: 27px;\n overflow: hidden;\n padding: 0 4px 0 5px; }\n .dg li.folder {\n padding: 0;\n border-left: 4px solid rgba(0, 0, 0, 0); }\n .dg li.title {\n cursor: pointer;\n margin-left: -4px; }\n .dg .closed li:not(.title),\n .dg .closed ul li,\n .dg .closed ul li > * {\n height: 0;\n overflow: hidden;\n border: 0; }\n .dg .cr {\n clear: both;\n padding-left: 3px;\n height: 27px; }\n .dg .property-name {\n cursor: default;\n float: left;\n clear: left;\n width: 40%;\n overflow: hidden;\n text-overflow: ellipsis; }\n .dg .c {\n float: left;\n width: 60%; }\n .dg .c input[type=text] {\n border: 0;\n margin-top: 4px;\n padding: 3px;\n width: 100%;\n float: right; }\n .dg .has-slider input[type=text] {\n width: 30%;\n /*display: none;*/\n margin-left: 0; }\n .dg .slider {\n float: left;\n width: 66%;\n margin-left: -5px;\n margin-right: 0;\n height: 19px;\n margin-top: 4px; }\n .dg .slider-fg {\n height: 100%; }\n .dg .c input[type=checkbox] {\n margin-top: 9px; }\n .dg .c select {\n margin-top: 5px; }\n .dg .cr.function,\n .dg .cr.function .property-name,\n .dg .cr.function *,\n .dg .cr.boolean,\n .dg .cr.boolean * {\n cursor: pointer; }\n .dg .selector {\n display: none;\n position: absolute;\n margin-left: -9px;\n margin-top: 23px;\n z-index: 10; }\n .dg .c:hover .selector,\n .dg .selector.drag {\n display: block; }\n .dg li.save-row {\n padding: 0; }\n .dg li.save-row .button {\n display: inline-block;\n padding: 0px 6px; }\n .dg.dialogue {\n background-color: #222;\n width: 460px;\n padding: 15px;\n font-size: 13px;\n line-height: 15px; }\n\n/* TODO Separate style and structure */\n#dg-new-constructor {\n padding: 10px;\n color: #222;\n font-family: Monaco, monospace;\n font-size: 10px;\n border: 0;\n resize: none;\n box-shadow: inset 1px 1px 1px #888;\n word-wrap: break-word;\n margin: 12px 0;\n display: block;\n width: 440px;\n overflow-y: scroll;\n height: 100px;\n position: relative; }\n\n#dg-local-explain {\n display: none;\n font-size: 11px;\n line-height: 17px;\n border-radius: 3px;\n background-color: #333;\n padding: 8px;\n margin-top: 10px; }\n #dg-local-explain code {\n font-size: 10px; }\n\n#dat-gui-save-locally {\n display: none; }\n\n/** Main type */\n.dg {\n color: #eee;\n font: 11px 'Lucida Grande', sans-serif;\n text-shadow: 0 -1px 0 #111;\n /** Auto place */\n /* Controller row,
  • */\n /** Controllers */ }\n .dg.main {\n /** Scrollbar */ }\n .dg.main::-webkit-scrollbar {\n width: 5px;\n background: #1a1a1a; }\n .dg.main::-webkit-scrollbar-corner {\n height: 0;\n display: none; }\n .dg.main::-webkit-scrollbar-thumb {\n border-radius: 5px;\n background: #676767; }\n .dg li:not(.folder) {\n background: #1a1a1a;\n border-bottom: 1px solid #2c2c2c; }\n .dg li.save-row {\n line-height: 25px;\n background: #dad5cb;\n border: 0; }\n .dg li.save-row select {\n margin-left: 5px;\n width: 108px; }\n .dg li.save-row .button {\n margin-left: 5px;\n margin-top: 1px;\n border-radius: 2px;\n font-size: 9px;\n line-height: 7px;\n padding: 4px 4px 5px 4px;\n background: #c5bdad;\n color: #fff;\n text-shadow: 0 1px 0 #b0a58f;\n box-shadow: 0 -1px 0 #b0a58f;\n cursor: pointer; }\n .dg li.save-row .button.gears {\n background: #c5bdad url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAANCAYAAAB/9ZQ7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQJJREFUeNpiYKAU/P//PwGIC/ApCABiBSAW+I8AClAcgKxQ4T9hoMAEUrxx2QSGN6+egDX+/vWT4e7N82AMYoPAx/evwWoYoSYbACX2s7KxCxzcsezDh3evFoDEBYTEEqycggWAzA9AuUSQQgeYPa9fPv6/YWm/Acx5IPb7ty/fw+QZblw67vDs8R0YHyQhgObx+yAJkBqmG5dPPDh1aPOGR/eugW0G4vlIoTIfyFcA+QekhhHJhPdQxbiAIguMBTQZrPD7108M6roWYDFQiIAAv6Aow/1bFwXgis+f2LUAynwoIaNcz8XNx3Dl7MEJUDGQpx9gtQ8YCueB+D26OECAAQDadt7e46D42QAAAABJRU5ErkJggg==) 2px 1px no-repeat;\n height: 7px;\n width: 8px; }\n .dg li.save-row .button:hover {\n background-color: #bab19e;\n box-shadow: 0 -1px 0 #b0a58f; }\n .dg li.folder {\n border-bottom: 0; }\n .dg li.title {\n padding-left: 16px;\n background: black url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlI+hKgFxoCgAOw==) 6px 10px no-repeat;\n cursor: pointer;\n border-bottom: 1px solid rgba(255, 255, 255, 0.2); }\n .dg .closed li.title {\n background-image: url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlGIWqMCbWAEAOw==); }\n .dg .cr.boolean {\n border-left: 3px solid #806787; }\n .dg .cr.function {\n border-left: 3px solid #e61d5f; }\n .dg .cr.number {\n border-left: 3px solid #2fa1d6; }\n .dg .cr.number input[type=text] {\n color: #2fa1d6; }\n .dg .cr.string {\n border-left: 3px solid #1ed36f; }\n .dg .cr.string input[type=text] {\n color: #1ed36f; }\n .dg .cr.function:hover, .dg .cr.boolean:hover {\n background: #111; }\n .dg .c input[type=text] {\n background: #303030;\n outline: none; }\n .dg .c input[type=text]:hover {\n background: #3c3c3c; }\n .dg .c input[type=text]:focus {\n background: #494949;\n color: #fff; }\n .dg .c .slider {\n background: #303030;\n cursor: ew-resize; }\n .dg .c .slider-fg {\n background: #2fa1d6; }\n .dg .c .slider:hover {\n background: #3c3c3c; }\n .dg .c .slider:hover .slider-fg {\n background: #44abda; }\n", +dat.controllers.factory=function(f,a,d,e,c,b,p){return function(q,l,r,n){var u=q[l];if(p.isArray(r)||p.isObject(r))return new f(q,l,r);if(p.isNumber(u))return p.isNumber(r)&&p.isNumber(n)?new d(q,l,r,n):new a(q,l,{min:r,max:n});if(p.isString(u))return new e(q,l);if(p.isFunction(u))return new c(q,l,"");if(p.isBoolean(u))return new b(q,l)}}(dat.controllers.OptionController,dat.controllers.NumberControllerBox,dat.controllers.NumberControllerSlider,dat.controllers.StringController=function(f,a,d){var e= +function(c,b){function d(){f.setValue(f.__input.value)}e.superclass.call(this,c,b);var f=this;this.__input=document.createElement("input");this.__input.setAttribute("type","text");a.bind(this.__input,"keyup",d);a.bind(this.__input,"change",d);a.bind(this.__input,"blur",function(){f.__onFinishChange&&f.__onFinishChange.call(f,f.getValue())});a.bind(this.__input,"keydown",function(a){13===a.keyCode&&this.blur()});this.updateDisplay();this.domElement.appendChild(this.__input)};e.superclass=f;d.extend(e.prototype, +f.prototype,{updateDisplay:function(){a.isActive(this.__input)||(this.__input.value=this.getValue());return e.superclass.prototype.updateDisplay.call(this)}});return e}(dat.controllers.Controller,dat.dom.dom,dat.utils.common),dat.controllers.FunctionController,dat.controllers.BooleanController,dat.utils.common),dat.controllers.Controller,dat.controllers.BooleanController,dat.controllers.FunctionController,dat.controllers.NumberControllerBox,dat.controllers.NumberControllerSlider,dat.controllers.OptionController, +dat.controllers.ColorController=function(f,a,d,e,c){function b(a,b,d,e){a.style.background="";c.each(l,function(c){a.style.cssText+="background: "+c+"linear-gradient("+b+", "+d+" 0%, "+e+" 100%); "})}function p(a){a.style.background="";a.style.cssText+="background: -moz-linear-gradient(top, #ff0000 0%, #ff00ff 17%, #0000ff 34%, #00ffff 50%, #00ff00 67%, #ffff00 84%, #ff0000 100%);";a.style.cssText+="background: -webkit-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);"; +a.style.cssText+="background: -o-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);";a.style.cssText+="background: -ms-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);";a.style.cssText+="background: linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);"}var q=function(f,n){function u(b){v(b);a.bind(window,"mousemove",v);a.bind(window, +"mouseup",l)}function l(){a.unbind(window,"mousemove",v);a.unbind(window,"mouseup",l)}function g(){var a=e(this.value);!1!==a?(t.__color.__state=a,t.setValue(t.__color.toOriginal())):this.value=t.__color.toString()}function k(){a.unbind(window,"mousemove",w);a.unbind(window,"mouseup",k)}function v(b){b.preventDefault();var c=a.getWidth(t.__saturation_field),d=a.getOffset(t.__saturation_field),e=(b.clientX-d.left+document.body.scrollLeft)/c;b=1-(b.clientY-d.top+document.body.scrollTop)/c;1 +b&&(b=0);1e&&(e=0);t.__color.v=b;t.__color.s=e;t.setValue(t.__color.toOriginal());return!1}function w(b){b.preventDefault();var c=a.getHeight(t.__hue_field),d=a.getOffset(t.__hue_field);b=1-(b.clientY-d.top+document.body.scrollTop)/c;1b&&(b=0);t.__color.h=360*b;t.setValue(t.__color.toOriginal());return!1}q.superclass.call(this,f,n);this.__color=new d(this.getValue());this.__temp=new d(0);var t=this;this.domElement=document.createElement("div");a.makeSelectable(this.domElement,!1); +this.__selector=document.createElement("div");this.__selector.className="selector";this.__saturation_field=document.createElement("div");this.__saturation_field.className="saturation-field";this.__field_knob=document.createElement("div");this.__field_knob.className="field-knob";this.__field_knob_border="2px solid ";this.__hue_knob=document.createElement("div");this.__hue_knob.className="hue-knob";this.__hue_field=document.createElement("div");this.__hue_field.className="hue-field";this.__input=document.createElement("input"); +this.__input.type="text";this.__input_textShadow="0 1px 1px ";a.bind(this.__input,"keydown",function(a){13===a.keyCode&&g.call(this)});a.bind(this.__input,"blur",g);a.bind(this.__selector,"mousedown",function(b){a.addClass(this,"drag").bind(window,"mouseup",function(b){a.removeClass(t.__selector,"drag")})});var y=document.createElement("div");c.extend(this.__selector.style,{width:"122px",height:"102px",padding:"3px",backgroundColor:"#222",boxShadow:"0px 1px 3px rgba(0,0,0,0.3)"});c.extend(this.__field_knob.style, +{position:"absolute",width:"12px",height:"12px",border:this.__field_knob_border+(.5>this.__color.v?"#fff":"#000"),boxShadow:"0px 1px 3px rgba(0,0,0,0.5)",borderRadius:"12px",zIndex:1});c.extend(this.__hue_knob.style,{position:"absolute",width:"15px",height:"2px",borderRight:"4px solid #fff",zIndex:1});c.extend(this.__saturation_field.style,{width:"100px",height:"100px",border:"1px solid #555",marginRight:"3px",display:"inline-block",cursor:"pointer"});c.extend(y.style,{width:"100%",height:"100%", +background:"none"});b(y,"top","rgba(0,0,0,0)","#000");c.extend(this.__hue_field.style,{width:"15px",height:"100px",display:"inline-block",border:"1px solid #555",cursor:"ns-resize"});p(this.__hue_field);c.extend(this.__input.style,{outline:"none",textAlign:"center",color:"#fff",border:0,fontWeight:"bold",textShadow:this.__input_textShadow+"rgba(0,0,0,0.7)"});a.bind(this.__saturation_field,"mousedown",u);a.bind(this.__field_knob,"mousedown",u);a.bind(this.__hue_field,"mousedown",function(b){w(b);a.bind(window, +"mousemove",w);a.bind(window,"mouseup",k)});this.__saturation_field.appendChild(y);this.__selector.appendChild(this.__field_knob);this.__selector.appendChild(this.__saturation_field);this.__selector.appendChild(this.__hue_field);this.__hue_field.appendChild(this.__hue_knob);this.domElement.appendChild(this.__input);this.domElement.appendChild(this.__selector);this.updateDisplay()};q.superclass=f;c.extend(q.prototype,f.prototype,{updateDisplay:function(){var a=e(this.getValue());if(!1!==a){var f=!1; +c.each(d.COMPONENTS,function(b){if(!c.isUndefined(a[b])&&!c.isUndefined(this.__color.__state[b])&&a[b]!==this.__color.__state[b])return f=!0,{}},this);f&&c.extend(this.__color.__state,a)}c.extend(this.__temp.__state,this.__color.__state);this.__temp.a=1;var l=.5>this.__color.v||.5a&&(a+=1);return{h:360*a,s:c/b,v:b/255}},rgb_to_hex:function(a,d,e){a=this.hex_with_component(0,2,a);a=this.hex_with_component(a,1,d);return a=this.hex_with_component(a,0,e)},component_from_hex:function(a,d){return a>>8*d&255},hex_with_component:function(a,d,e){return e<<(f=8*d)|a&~(255<"))}function a(t){var i="button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";return t.delegate(i,"mouseout",function(){e(this).removeClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&e(this).removeClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&e(this).removeClass("ui-datepicker-next-hover")}).delegate(i,"mouseover",o)}function o(){e.datepicker._isDisabledDatepicker(v.inline?v.dpDiv.parent()[0]:v.input[0])||(e(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"),e(this).addClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&e(this).addClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&e(this).addClass("ui-datepicker-next-hover"))}function r(t,i){e.extend(t,i);for(var s in i)null==i[s]&&(t[s]=i[s]);return t}function h(e){return function(){var t=this.element.val();e.apply(this,arguments),this._refresh(),t!==this.element.val()&&this._trigger("change")}}e.ui=e.ui||{},e.extend(e.ui,{version:"1.11.4",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({scrollParent:function(t){var i=this.css("position"),s="absolute"===i,n=t?/(auto|scroll|hidden)/:/(auto|scroll)/,a=this.parents().filter(function(){var t=e(this);return s&&"static"===t.css("position")?!1:n.test(t.css("overflow")+t.css("overflow-y")+t.css("overflow-x"))}).eq(0);return"fixed"!==i&&a.length?a:e(this[0].ownerDocument||document)},uniqueId:function(){var e=0;return function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++e)})}}(),removeUniqueId:function(){return this.each(function(){/^ui-id-\d+$/.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(i){return!!e.data(i,t)}}):function(t,i,s){return!!e.data(t,s[3])},focusable:function(i){return t(i,!isNaN(e.attr(i,"tabindex")))},tabbable:function(i){var s=e.attr(i,"tabindex"),n=isNaN(s);return(n||s>=0)&&t(i,!n)}}),e("").outerWidth(1).jquery||e.each(["Width","Height"],function(t,i){function s(t,i,s,a){return e.each(n,function(){i-=parseFloat(e.css(t,"padding"+this))||0,s&&(i-=parseFloat(e.css(t,"border"+this+"Width"))||0),a&&(i-=parseFloat(e.css(t,"margin"+this))||0)}),i}var n="Width"===i?["Left","Right"]:["Top","Bottom"],a=i.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+i]=function(t){return void 0===t?o["inner"+i].call(this):this.each(function(){e(this).css(a,s(this,t)+"px")})},e.fn["outer"+i]=function(t,n){return"number"!=typeof t?o["outer"+i].call(this,t):this.each(function(){e(this).css(a,s(this,t,!0,n)+"px")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e("").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(i){return arguments.length?t.call(this,e.camelCase(i)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),e.fn.extend({focus:function(t){return function(i,s){return"number"==typeof i?this.each(function(){var t=this;setTimeout(function(){e(t).focus(),s&&s.call(t)},i)}):t.apply(this,arguments)}}(e.fn.focus),disableSelection:function(){var e="onselectstart"in document.createElement("div")?"selectstart":"mousedown";return function(){return this.bind(e+".ui-disableSelection",function(e){e.preventDefault()})}}(),enableSelection:function(){return this.unbind(".ui-disableSelection")},zIndex:function(t){if(void 0!==t)return this.css("zIndex",t);if(this.length)for(var i,s,n=e(this[0]);n.length&&n[0]!==document;){if(i=n.css("position"),("absolute"===i||"relative"===i||"fixed"===i)&&(s=parseInt(n.css("zIndex"),10),!isNaN(s)&&0!==s))return s;n=n.parent()}return 0}}),e.ui.plugin={add:function(t,i,s){var n,a=e.ui[t].prototype;for(n in s)a.plugins[n]=a.plugins[n]||[],a.plugins[n].push([i,s[n]])},call:function(e,t,i,s){var n,a=e.plugins[t];if(a&&(s||e.element[0].parentNode&&11!==e.element[0].parentNode.nodeType))for(n=0;a.length>n;n++)e.options[a[n][0]]&&a[n][1].apply(e.element,i)}};var l=0,u=Array.prototype.slice;e.cleanData=function(t){return function(i){var s,n,a;for(a=0;null!=(n=i[a]);a++)try{s=e._data(n,"events"),s&&s.remove&&e(n).triggerHandler("remove")}catch(o){}t(i)}}(e.cleanData),e.widget=function(t,i,s){var n,a,o,r,h={},l=t.split(".")[0];return t=t.split(".")[1],n=l+"-"+t,s||(s=i,i=e.Widget),e.expr[":"][n.toLowerCase()]=function(t){return!!e.data(t,n)},e[l]=e[l]||{},a=e[l][t],o=e[l][t]=function(e,t){return this._createWidget?(arguments.length&&this._createWidget(e,t),void 0):new o(e,t)},e.extend(o,a,{version:s.version,_proto:e.extend({},s),_childConstructors:[]}),r=new i,r.options=e.widget.extend({},r.options),e.each(s,function(t,s){return e.isFunction(s)?(h[t]=function(){var e=function(){return i.prototype[t].apply(this,arguments)},n=function(e){return i.prototype[t].apply(this,e)};return function(){var t,i=this._super,a=this._superApply;return this._super=e,this._superApply=n,t=s.apply(this,arguments),this._super=i,this._superApply=a,t}}(),void 0):(h[t]=s,void 0)}),o.prototype=e.widget.extend(r,{widgetEventPrefix:a?r.widgetEventPrefix||t:t},h,{constructor:o,namespace:l,widgetName:t,widgetFullName:n}),a?(e.each(a._childConstructors,function(t,i){var s=i.prototype;e.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete a._childConstructors):i._childConstructors.push(o),e.widget.bridge(t,o),o},e.widget.extend=function(t){for(var i,s,n=u.call(arguments,1),a=0,o=n.length;o>a;a++)for(i in n[a])s=n[a][i],n[a].hasOwnProperty(i)&&void 0!==s&&(t[i]=e.isPlainObject(s)?e.isPlainObject(t[i])?e.widget.extend({},t[i],s):e.widget.extend({},s):s);return t},e.widget.bridge=function(t,i){var s=i.prototype.widgetFullName||t;e.fn[t]=function(n){var a="string"==typeof n,o=u.call(arguments,1),r=this;return a?this.each(function(){var i,a=e.data(this,s);return"instance"===n?(r=a,!1):a?e.isFunction(a[n])&&"_"!==n.charAt(0)?(i=a[n].apply(a,o),i!==a&&void 0!==i?(r=i&&i.jquery?r.pushStack(i.get()):i,!1):void 0):e.error("no such method '"+n+"' for "+t+" widget instance"):e.error("cannot call methods on "+t+" prior to initialization; "+"attempted to call method '"+n+"'")}):(o.length&&(n=e.widget.extend.apply(null,[n].concat(o))),this.each(function(){var t=e.data(this,s);t?(t.option(n||{}),t._init&&t._init()):e.data(this,s,new i(n,this))})),r}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"
    ",options:{disabled:!1,create:null},_createWidget:function(t,i){i=e(i||this.defaultElement||this)[0],this.element=e(i),this.uuid=l++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=e(),this.hoverable=e(),this.focusable=e(),i!==this&&(e.data(i,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===i&&this.destroy()}}),this.document=e(i.style?i.ownerDocument:i.document||i),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(t,i){var s,n,a,o=t;if(0===arguments.length)return e.widget.extend({},this.options);if("string"==typeof t)if(o={},s=t.split("."),t=s.shift(),s.length){for(n=o[t]=e.widget.extend({},this.options[t]),a=0;s.length-1>a;a++)n[s[a]]=n[s[a]]||{},n=n[s[a]];if(t=s.pop(),1===arguments.length)return void 0===n[t]?null:n[t];n[t]=i}else{if(1===arguments.length)return void 0===this.options[t]?null:this.options[t];o[t]=i}return this._setOptions(o),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,"disabled"===e&&(this.widget().toggleClass(this.widgetFullName+"-disabled",!!t),t&&(this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus"))),this},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_on:function(t,i,s){var n,a=this;"boolean"!=typeof t&&(s=i,i=t,t=!1),s?(i=n=e(i),this.bindings=this.bindings.add(i)):(s=i,i=this.element,n=this.widget()),e.each(s,function(s,o){function r(){return t||a.options.disabled!==!0&&!e(this).hasClass("ui-state-disabled")?("string"==typeof o?a[o]:o).apply(a,arguments):void 0}"string"!=typeof o&&(r.guid=o.guid=o.guid||r.guid||e.guid++);var h=s.match(/^([\w:-]*)\s*(.*)$/),l=h[1]+a.eventNamespace,u=h[2];u?n.delegate(u,l,r):i.bind(l,r)})},_off:function(t,i){i=(i||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,t.unbind(i).undelegate(i),this.bindings=e(this.bindings.not(t).get()),this.focusable=e(this.focusable.not(t).get()),this.hoverable=e(this.hoverable.not(t).get())},_delay:function(e,t){function i(){return("string"==typeof e?s[e]:e).apply(s,arguments)}var s=this;return setTimeout(i,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,i,s){var n,a,o=this.options[t];if(s=s||{},i=e.Event(i),i.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),i.target=this.element[0],a=i.originalEvent)for(n in a)n in i||(i[n]=a[n]);return this.element.trigger(i,s),!(e.isFunction(o)&&o.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,i){e.Widget.prototype["_"+t]=function(s,n,a){"string"==typeof n&&(n={effect:n});var o,r=n?n===!0||"number"==typeof n?i:n.effect||i:t;n=n||{},"number"==typeof n&&(n={duration:n}),o=!e.isEmptyObject(n),n.complete=a,n.delay&&s.delay(n.delay),o&&e.effects&&e.effects.effect[r]?s[t](n):r!==t&&s[r]?s[r](n.duration,n.easing,a):s.queue(function(i){e(this)[t](),a&&a.call(s[0]),i()})}}),e.widget;var d=!1;e(document).mouseup(function(){d=!1}),e.widget("ui.mouse",{version:"1.11.4",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var t=this;this.element.bind("mousedown."+this.widgetName,function(e){return t._mouseDown(e)}).bind("click."+this.widgetName,function(i){return!0===e.data(i.target,t.widgetName+".preventClickEvent")?(e.removeData(i.target,t.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):void 0}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&this.document.unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(t){if(!d){this._mouseMoved=!1,this._mouseStarted&&this._mouseUp(t),this._mouseDownEvent=t;var i=this,s=1===t.which,n="string"==typeof this.options.cancel&&t.target.nodeName?e(t.target).closest(this.options.cancel).length:!1;return s&&!n&&this._mouseCapture(t)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){i.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(t)!==!1,!this._mouseStarted)?(t.preventDefault(),!0):(!0===e.data(t.target,this.widgetName+".preventClickEvent")&&e.removeData(t.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(e){return i._mouseMove(e)},this._mouseUpDelegate=function(e){return i._mouseUp(e)},this.document.bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),t.preventDefault(),d=!0,!0)):!0}},_mouseMove:function(t){if(this._mouseMoved){if(e.ui.ie&&(!document.documentMode||9>document.documentMode)&&!t.button)return this._mouseUp(t);if(!t.which)return this._mouseUp(t)}return(t.which||t.button)&&(this._mouseMoved=!0),this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted)},_mouseUp:function(t){return this.document.unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(t)),d=!1,!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}}),function(){function t(e,t,i){return[parseFloat(e[0])*(p.test(e[0])?t/100:1),parseFloat(e[1])*(p.test(e[1])?i/100:1)]}function i(t,i){return parseInt(e.css(t,i),10)||0}function s(t){var i=t[0];return 9===i.nodeType?{width:t.width(),height:t.height(),offset:{top:0,left:0}}:e.isWindow(i)?{width:t.width(),height:t.height(),offset:{top:t.scrollTop(),left:t.scrollLeft()}}:i.preventDefault?{width:0,height:0,offset:{top:i.pageY,left:i.pageX}}:{width:t.outerWidth(),height:t.outerHeight(),offset:t.offset()}}e.ui=e.ui||{};var n,a,o=Math.max,r=Math.abs,h=Math.round,l=/left|center|right/,u=/top|center|bottom/,d=/[\+\-]\d+(\.[\d]+)?%?/,c=/^\w+/,p=/%$/,f=e.fn.position;e.position={scrollbarWidth:function(){if(void 0!==n)return n;var t,i,s=e("
    "),a=s.children()[0];return e("body").append(s),t=a.offsetWidth,s.css("overflow","scroll"),i=a.offsetWidth,t===i&&(i=s[0].clientWidth),s.remove(),n=t-i},getScrollInfo:function(t){var i=t.isWindow||t.isDocument?"":t.element.css("overflow-x"),s=t.isWindow||t.isDocument?"":t.element.css("overflow-y"),n="scroll"===i||"auto"===i&&t.widthi?"left":t>0?"right":"center",vertical:0>a?"top":s>0?"bottom":"middle"};d>m&&m>r(t+i)&&(h.horizontal="center"),c>g&&g>r(s+a)&&(h.vertical="middle"),h.important=o(r(t),r(i))>o(r(s),r(a))?"horizontal":"vertical",n.using.call(this,e,h)}),u.offset(e.extend(M,{using:l}))})},e.ui.position={fit:{left:function(e,t){var i,s=t.within,n=s.isWindow?s.scrollLeft:s.offset.left,a=s.width,r=e.left-t.collisionPosition.marginLeft,h=n-r,l=r+t.collisionWidth-a-n;t.collisionWidth>a?h>0&&0>=l?(i=e.left+h+t.collisionWidth-a-n,e.left+=h-i):e.left=l>0&&0>=h?n:h>l?n+a-t.collisionWidth:n:h>0?e.left+=h:l>0?e.left-=l:e.left=o(e.left-r,e.left)},top:function(e,t){var i,s=t.within,n=s.isWindow?s.scrollTop:s.offset.top,a=t.within.height,r=e.top-t.collisionPosition.marginTop,h=n-r,l=r+t.collisionHeight-a-n;t.collisionHeight>a?h>0&&0>=l?(i=e.top+h+t.collisionHeight-a-n,e.top+=h-i):e.top=l>0&&0>=h?n:h>l?n+a-t.collisionHeight:n:h>0?e.top+=h:l>0?e.top-=l:e.top=o(e.top-r,e.top)}},flip:{left:function(e,t){var i,s,n=t.within,a=n.offset.left+n.scrollLeft,o=n.width,h=n.isWindow?n.scrollLeft:n.offset.left,l=e.left-t.collisionPosition.marginLeft,u=l-h,d=l+t.collisionWidth-o-h,c="left"===t.my[0]?-t.elemWidth:"right"===t.my[0]?t.elemWidth:0,p="left"===t.at[0]?t.targetWidth:"right"===t.at[0]?-t.targetWidth:0,f=-2*t.offset[0];0>u?(i=e.left+c+p+f+t.collisionWidth-o-a,(0>i||r(u)>i)&&(e.left+=c+p+f)):d>0&&(s=e.left-t.collisionPosition.marginLeft+c+p+f-h,(s>0||d>r(s))&&(e.left+=c+p+f))},top:function(e,t){var i,s,n=t.within,a=n.offset.top+n.scrollTop,o=n.height,h=n.isWindow?n.scrollTop:n.offset.top,l=e.top-t.collisionPosition.marginTop,u=l-h,d=l+t.collisionHeight-o-h,c="top"===t.my[1],p=c?-t.elemHeight:"bottom"===t.my[1]?t.elemHeight:0,f="top"===t.at[1]?t.targetHeight:"bottom"===t.at[1]?-t.targetHeight:0,m=-2*t.offset[1];0>u?(s=e.top+p+f+m+t.collisionHeight-o-a,(0>s||r(u)>s)&&(e.top+=p+f+m)):d>0&&(i=e.top-t.collisionPosition.marginTop+p+f+m-h,(i>0||d>r(i))&&(e.top+=p+f+m))}},flipfit:{left:function(){e.ui.position.flip.left.apply(this,arguments),e.ui.position.fit.left.apply(this,arguments)},top:function(){e.ui.position.flip.top.apply(this,arguments),e.ui.position.fit.top.apply(this,arguments)}}},function(){var t,i,s,n,o,r=document.getElementsByTagName("body")[0],h=document.createElement("div");t=document.createElement(r?"div":"body"),s={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},r&&e.extend(s,{position:"absolute",left:"-1000px",top:"-1000px"});for(o in s)t.style[o]=s[o];t.appendChild(h),i=r||document.documentElement,i.insertBefore(t,i.firstChild),h.style.cssText="position: absolute; left: 10.7432222px;",n=e(h).offset().left,a=n>10&&11>n,t.innerHTML="",i.removeChild(t)}()}(),e.ui.position,e.widget("ui.accordion",{version:"1.11.4",options:{active:0,animate:{},collapsible:!1,event:"click",header:"> li > :first-child,> :not(li):even",heightStyle:"auto",icons:{activeHeader:"ui-icon-triangle-1-s",header:"ui-icon-triangle-1-e"},activate:null,beforeActivate:null},hideProps:{borderTopWidth:"hide",borderBottomWidth:"hide",paddingTop:"hide",paddingBottom:"hide",height:"hide"},showProps:{borderTopWidth:"show",borderBottomWidth:"show",paddingTop:"show",paddingBottom:"show",height:"show"},_create:function(){var t=this.options;this.prevShow=this.prevHide=e(),this.element.addClass("ui-accordion ui-widget ui-helper-reset").attr("role","tablist"),t.collapsible||t.active!==!1&&null!=t.active||(t.active=0),this._processPanels(),0>t.active&&(t.active+=this.headers.length),this._refresh()},_getCreateEventData:function(){return{header:this.active,panel:this.active.length?this.active.next():e()}},_createIcons:function(){var t=this.options.icons;t&&(e("").addClass("ui-accordion-header-icon ui-icon "+t.header).prependTo(this.headers),this.active.children(".ui-accordion-header-icon").removeClass(t.header).addClass(t.activeHeader),this.headers.addClass("ui-accordion-icons"))},_destroyIcons:function(){this.headers.removeClass("ui-accordion-icons").children(".ui-accordion-header-icon").remove()},_destroy:function(){var e;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role"),this.headers.removeClass("ui-accordion-header ui-accordion-header-active ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-selected").removeAttr("aria-controls").removeAttr("tabIndex").removeUniqueId(),this._destroyIcons(),e=this.headers.next().removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled").css("display","").removeAttr("role").removeAttr("aria-hidden").removeAttr("aria-labelledby").removeUniqueId(),"content"!==this.options.heightStyle&&e.css("height","")},_setOption:function(e,t){return"active"===e?(this._activate(t),void 0):("event"===e&&(this.options.event&&this._off(this.headers,this.options.event),this._setupEvents(t)),this._super(e,t),"collapsible"!==e||t||this.options.active!==!1||this._activate(0),"icons"===e&&(this._destroyIcons(),t&&this._createIcons()),"disabled"===e&&(this.element.toggleClass("ui-state-disabled",!!t).attr("aria-disabled",t),this.headers.add(this.headers.next()).toggleClass("ui-state-disabled",!!t)),void 0)},_keydown:function(t){if(!t.altKey&&!t.ctrlKey){var i=e.ui.keyCode,s=this.headers.length,n=this.headers.index(t.target),a=!1;switch(t.keyCode){case i.RIGHT:case i.DOWN:a=this.headers[(n+1)%s];break;case i.LEFT:case i.UP:a=this.headers[(n-1+s)%s];break;case i.SPACE:case i.ENTER:this._eventHandler(t);break;case i.HOME:a=this.headers[0];break;case i.END:a=this.headers[s-1]}a&&(e(t.target).attr("tabIndex",-1),e(a).attr("tabIndex",0),a.focus(),t.preventDefault())}},_panelKeyDown:function(t){t.keyCode===e.ui.keyCode.UP&&t.ctrlKey&&e(t.currentTarget).prev().focus()},refresh:function(){var t=this.options;this._processPanels(),t.active===!1&&t.collapsible===!0||!this.headers.length?(t.active=!1,this.active=e()):t.active===!1?this._activate(0):this.active.length&&!e.contains(this.element[0],this.active[0])?this.headers.length===this.headers.find(".ui-state-disabled").length?(t.active=!1,this.active=e()):this._activate(Math.max(0,t.active-1)):t.active=this.headers.index(this.active),this._destroyIcons(),this._refresh()},_processPanels:function(){var e=this.headers,t=this.panels;this.headers=this.element.find(this.options.header).addClass("ui-accordion-header ui-state-default ui-corner-all"),this.panels=this.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom").filter(":not(.ui-accordion-content-active)").hide(),t&&(this._off(e.not(this.headers)),this._off(t.not(this.panels)))},_refresh:function(){var t,i=this.options,s=i.heightStyle,n=this.element.parent();this.active=this._findActive(i.active).addClass("ui-accordion-header-active ui-state-active ui-corner-top").removeClass("ui-corner-all"),this.active.next().addClass("ui-accordion-content-active").show(),this.headers.attr("role","tab").each(function(){var t=e(this),i=t.uniqueId().attr("id"),s=t.next(),n=s.uniqueId().attr("id");t.attr("aria-controls",n),s.attr("aria-labelledby",i)}).next().attr("role","tabpanel"),this.headers.not(this.active).attr({"aria-selected":"false","aria-expanded":"false",tabIndex:-1}).next().attr({"aria-hidden":"true"}).hide(),this.active.length?this.active.attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0}).next().attr({"aria-hidden":"false"}):this.headers.eq(0).attr("tabIndex",0),this._createIcons(),this._setupEvents(i.event),"fill"===s?(t=n.height(),this.element.siblings(":visible").each(function(){var i=e(this),s=i.css("position");"absolute"!==s&&"fixed"!==s&&(t-=i.outerHeight(!0))}),this.headers.each(function(){t-=e(this).outerHeight(!0)}),this.headers.next().each(function(){e(this).height(Math.max(0,t-e(this).innerHeight()+e(this).height()))}).css("overflow","auto")):"auto"===s&&(t=0,this.headers.next().each(function(){t=Math.max(t,e(this).css("height","").height())}).height(t))},_activate:function(t){var i=this._findActive(t)[0];i!==this.active[0]&&(i=i||this.active[0],this._eventHandler({target:i,currentTarget:i,preventDefault:e.noop}))},_findActive:function(t){return"number"==typeof t?this.headers.eq(t):e()},_setupEvents:function(t){var i={keydown:"_keydown"};t&&e.each(t.split(" "),function(e,t){i[t]="_eventHandler"}),this._off(this.headers.add(this.headers.next())),this._on(this.headers,i),this._on(this.headers.next(),{keydown:"_panelKeyDown"}),this._hoverable(this.headers),this._focusable(this.headers)},_eventHandler:function(t){var i=this.options,s=this.active,n=e(t.currentTarget),a=n[0]===s[0],o=a&&i.collapsible,r=o?e():n.next(),h=s.next(),l={oldHeader:s,oldPanel:h,newHeader:o?e():n,newPanel:r};t.preventDefault(),a&&!i.collapsible||this._trigger("beforeActivate",t,l)===!1||(i.active=o?!1:this.headers.index(n),this.active=a?e():n,this._toggle(l),s.removeClass("ui-accordion-header-active ui-state-active"),i.icons&&s.children(".ui-accordion-header-icon").removeClass(i.icons.activeHeader).addClass(i.icons.header),a||(n.removeClass("ui-corner-all").addClass("ui-accordion-header-active ui-state-active ui-corner-top"),i.icons&&n.children(".ui-accordion-header-icon").removeClass(i.icons.header).addClass(i.icons.activeHeader),n.next().addClass("ui-accordion-content-active")))},_toggle:function(t){var i=t.newPanel,s=this.prevShow.length?this.prevShow:t.oldPanel;this.prevShow.add(this.prevHide).stop(!0,!0),this.prevShow=i,this.prevHide=s,this.options.animate?this._animate(i,s,t):(s.hide(),i.show(),this._toggleComplete(t)),s.attr({"aria-hidden":"true"}),s.prev().attr({"aria-selected":"false","aria-expanded":"false"}),i.length&&s.length?s.prev().attr({tabIndex:-1,"aria-expanded":"false"}):i.length&&this.headers.filter(function(){return 0===parseInt(e(this).attr("tabIndex"),10)}).attr("tabIndex",-1),i.attr("aria-hidden","false").prev().attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0})},_animate:function(e,t,i){var s,n,a,o=this,r=0,h=e.css("box-sizing"),l=e.length&&(!t.length||e.index()",delay:300,options:{icons:{submenu:"ui-icon-carat-1-e"},items:"> *",menus:"ul",position:{my:"left-1 top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.mouseHandled=!1,this.element.uniqueId().addClass("ui-menu ui-widget ui-widget-content").toggleClass("ui-menu-icons",!!this.element.find(".ui-icon").length).attr({role:this.options.role,tabIndex:0}),this.options.disabled&&this.element.addClass("ui-state-disabled").attr("aria-disabled","true"),this._on({"mousedown .ui-menu-item":function(e){e.preventDefault()},"click .ui-menu-item":function(t){var i=e(t.target);!this.mouseHandled&&i.not(".ui-state-disabled").length&&(this.select(t),t.isPropagationStopped()||(this.mouseHandled=!0),i.has(".ui-menu").length?this.expand(t):!this.element.is(":focus")&&e(this.document[0].activeElement).closest(".ui-menu").length&&(this.element.trigger("focus",[!0]),this.active&&1===this.active.parents(".ui-menu").length&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":function(t){if(!this.previousFilter){var i=e(t.currentTarget); +i.siblings(".ui-state-active").removeClass("ui-state-active"),this.focus(t,i)}},mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(e,t){var i=this.active||this.element.find(this.options.items).eq(0);t||this.focus(e,i)},blur:function(t){this._delay(function(){e.contains(this.element[0],this.document[0].activeElement)||this.collapseAll(t)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(e){this._closeOnDocumentClick(e)&&this.collapseAll(e),this.mouseHandled=!1}})},_destroy:function(){this.element.removeAttr("aria-activedescendant").find(".ui-menu").addBack().removeClass("ui-menu ui-widget ui-widget-content ui-menu-icons ui-front").removeAttr("role").removeAttr("tabIndex").removeAttr("aria-labelledby").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-disabled").removeUniqueId().show(),this.element.find(".ui-menu-item").removeClass("ui-menu-item").removeAttr("role").removeAttr("aria-disabled").removeUniqueId().removeClass("ui-state-hover").removeAttr("tabIndex").removeAttr("role").removeAttr("aria-haspopup").children().each(function(){var t=e(this);t.data("ui-menu-submenu-carat")&&t.remove()}),this.element.find(".ui-menu-divider").removeClass("ui-menu-divider ui-widget-content")},_keydown:function(t){var i,s,n,a,o=!0;switch(t.keyCode){case e.ui.keyCode.PAGE_UP:this.previousPage(t);break;case e.ui.keyCode.PAGE_DOWN:this.nextPage(t);break;case e.ui.keyCode.HOME:this._move("first","first",t);break;case e.ui.keyCode.END:this._move("last","last",t);break;case e.ui.keyCode.UP:this.previous(t);break;case e.ui.keyCode.DOWN:this.next(t);break;case e.ui.keyCode.LEFT:this.collapse(t);break;case e.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(t);break;case e.ui.keyCode.ENTER:case e.ui.keyCode.SPACE:this._activate(t);break;case e.ui.keyCode.ESCAPE:this.collapse(t);break;default:o=!1,s=this.previousFilter||"",n=String.fromCharCode(t.keyCode),a=!1,clearTimeout(this.filterTimer),n===s?a=!0:n=s+n,i=this._filterMenuItems(n),i=a&&-1!==i.index(this.active.next())?this.active.nextAll(".ui-menu-item"):i,i.length||(n=String.fromCharCode(t.keyCode),i=this._filterMenuItems(n)),i.length?(this.focus(t,i),this.previousFilter=n,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter}o&&t.preventDefault()},_activate:function(e){this.active.is(".ui-state-disabled")||(this.active.is("[aria-haspopup='true']")?this.expand(e):this.select(e))},refresh:function(){var t,i,s=this,n=this.options.icons.submenu,a=this.element.find(this.options.menus);this.element.toggleClass("ui-menu-icons",!!this.element.find(".ui-icon").length),a.filter(":not(.ui-menu)").addClass("ui-menu ui-widget ui-widget-content ui-front").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"}).each(function(){var t=e(this),i=t.parent(),s=e("").addClass("ui-menu-icon ui-icon "+n).data("ui-menu-submenu-carat",!0);i.attr("aria-haspopup","true").prepend(s),t.attr("aria-labelledby",i.attr("id"))}),t=a.add(this.element),i=t.find(this.options.items),i.not(".ui-menu-item").each(function(){var t=e(this);s._isDivider(t)&&t.addClass("ui-widget-content ui-menu-divider")}),i.not(".ui-menu-item, .ui-menu-divider").addClass("ui-menu-item").uniqueId().attr({tabIndex:-1,role:this._itemRole()}),i.filter(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!e.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},_setOption:function(e,t){"icons"===e&&this.element.find(".ui-menu-icon").removeClass(this.options.icons.submenu).addClass(t.submenu),"disabled"===e&&this.element.toggleClass("ui-state-disabled",!!t).attr("aria-disabled",t),this._super(e,t)},focus:function(e,t){var i,s;this.blur(e,e&&"focus"===e.type),this._scrollIntoView(t),this.active=t.first(),s=this.active.addClass("ui-state-focus").removeClass("ui-state-active"),this.options.role&&this.element.attr("aria-activedescendant",s.attr("id")),this.active.parent().closest(".ui-menu-item").addClass("ui-state-active"),e&&"keydown"===e.type?this._close():this.timer=this._delay(function(){this._close()},this.delay),i=t.children(".ui-menu"),i.length&&e&&/^mouse/.test(e.type)&&this._startOpening(i),this.activeMenu=t.parent(),this._trigger("focus",e,{item:t})},_scrollIntoView:function(t){var i,s,n,a,o,r;this._hasScroll()&&(i=parseFloat(e.css(this.activeMenu[0],"borderTopWidth"))||0,s=parseFloat(e.css(this.activeMenu[0],"paddingTop"))||0,n=t.offset().top-this.activeMenu.offset().top-i-s,a=this.activeMenu.scrollTop(),o=this.activeMenu.height(),r=t.outerHeight(),0>n?this.activeMenu.scrollTop(a+n):n+r>o&&this.activeMenu.scrollTop(a+n-o+r))},blur:function(e,t){t||clearTimeout(this.timer),this.active&&(this.active.removeClass("ui-state-focus"),this.active=null,this._trigger("blur",e,{item:this.active}))},_startOpening:function(e){clearTimeout(this.timer),"true"===e.attr("aria-hidden")&&(this.timer=this._delay(function(){this._close(),this._open(e)},this.delay))},_open:function(t){var i=e.extend({of:this.active},this.options.position);clearTimeout(this.timer),this.element.find(".ui-menu").not(t.parents(".ui-menu")).hide().attr("aria-hidden","true"),t.show().removeAttr("aria-hidden").attr("aria-expanded","true").position(i)},collapseAll:function(t,i){clearTimeout(this.timer),this.timer=this._delay(function(){var s=i?this.element:e(t&&t.target).closest(this.element.find(".ui-menu"));s.length||(s=this.element),this._close(s),this.blur(t),this.activeMenu=s},this.delay)},_close:function(e){e||(e=this.active?this.active.parent():this.element),e.find(".ui-menu").hide().attr("aria-hidden","true").attr("aria-expanded","false").end().find(".ui-state-active").not(".ui-state-focus").removeClass("ui-state-active")},_closeOnDocumentClick:function(t){return!e(t.target).closest(".ui-menu").length},_isDivider:function(e){return!/[^\-\u2014\u2013\s]/.test(e.text())},collapse:function(e){var t=this.active&&this.active.parent().closest(".ui-menu-item",this.element);t&&t.length&&(this._close(),this.focus(e,t))},expand:function(e){var t=this.active&&this.active.children(".ui-menu ").find(this.options.items).first();t&&t.length&&(this._open(t.parent()),this._delay(function(){this.focus(e,t)}))},next:function(e){this._move("next","first",e)},previous:function(e){this._move("prev","last",e)},isFirstItem:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},isLastItem:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},_move:function(e,t,i){var s;this.active&&(s="first"===e||"last"===e?this.active["first"===e?"prevAll":"nextAll"](".ui-menu-item").eq(-1):this.active[e+"All"](".ui-menu-item").eq(0)),s&&s.length&&this.active||(s=this.activeMenu.find(this.options.items)[t]()),this.focus(i,s)},nextPage:function(t){var i,s,n;return this.active?(this.isLastItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.nextAll(".ui-menu-item").each(function(){return i=e(this),0>i.offset().top-s-n}),this.focus(t,i)):this.focus(t,this.activeMenu.find(this.options.items)[this.active?"last":"first"]())),void 0):(this.next(t),void 0)},previousPage:function(t){var i,s,n;return this.active?(this.isFirstItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.prevAll(".ui-menu-item").each(function(){return i=e(this),i.offset().top-s+n>0}),this.focus(t,i)):this.focus(t,this.activeMenu.find(this.options.items).first())),void 0):(this.next(t),void 0)},_hasScroll:function(){return this.element.outerHeight()",options:{appendTo:null,autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},requestIndex:0,pending:0,_create:function(){var t,i,s,n=this.element[0].nodeName.toLowerCase(),a="textarea"===n,o="input"===n;this.isMultiLine=a?!0:o?!1:this.element.prop("isContentEditable"),this.valueMethod=this.element[a||o?"val":"text"],this.isNewMenu=!0,this.element.addClass("ui-autocomplete-input").attr("autocomplete","off"),this._on(this.element,{keydown:function(n){if(this.element.prop("readOnly"))return t=!0,s=!0,i=!0,void 0;t=!1,s=!1,i=!1;var a=e.ui.keyCode;switch(n.keyCode){case a.PAGE_UP:t=!0,this._move("previousPage",n);break;case a.PAGE_DOWN:t=!0,this._move("nextPage",n);break;case a.UP:t=!0,this._keyEvent("previous",n);break;case a.DOWN:t=!0,this._keyEvent("next",n);break;case a.ENTER:this.menu.active&&(t=!0,n.preventDefault(),this.menu.select(n));break;case a.TAB:this.menu.active&&this.menu.select(n);break;case a.ESCAPE:this.menu.element.is(":visible")&&(this.isMultiLine||this._value(this.term),this.close(n),n.preventDefault());break;default:i=!0,this._searchTimeout(n)}},keypress:function(s){if(t)return t=!1,(!this.isMultiLine||this.menu.element.is(":visible"))&&s.preventDefault(),void 0;if(!i){var n=e.ui.keyCode;switch(s.keyCode){case n.PAGE_UP:this._move("previousPage",s);break;case n.PAGE_DOWN:this._move("nextPage",s);break;case n.UP:this._keyEvent("previous",s);break;case n.DOWN:this._keyEvent("next",s)}}},input:function(e){return s?(s=!1,e.preventDefault(),void 0):(this._searchTimeout(e),void 0)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(e){return this.cancelBlur?(delete this.cancelBlur,void 0):(clearTimeout(this.searching),this.close(e),this._change(e),void 0)}}),this._initSource(),this.menu=e("
      ").addClass("ui-autocomplete ui-front").appendTo(this._appendTo()).menu({role:null}).hide().menu("instance"),this._on(this.menu.element,{mousedown:function(t){t.preventDefault(),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur});var i=this.menu.element[0];e(t.target).closest(".ui-menu-item").length||this._delay(function(){var t=this;this.document.one("mousedown",function(s){s.target===t.element[0]||s.target===i||e.contains(i,s.target)||t.close()})})},menufocus:function(t,i){var s,n;return this.isNewMenu&&(this.isNewMenu=!1,t.originalEvent&&/^mouse/.test(t.originalEvent.type))?(this.menu.blur(),this.document.one("mousemove",function(){e(t.target).trigger(t.originalEvent)}),void 0):(n=i.item.data("ui-autocomplete-item"),!1!==this._trigger("focus",t,{item:n})&&t.originalEvent&&/^key/.test(t.originalEvent.type)&&this._value(n.value),s=i.item.attr("aria-label")||n.value,s&&e.trim(s).length&&(this.liveRegion.children().hide(),e("
      ").text(s).appendTo(this.liveRegion)),void 0)},menuselect:function(e,t){var i=t.item.data("ui-autocomplete-item"),s=this.previous;this.element[0]!==this.document[0].activeElement&&(this.element.focus(),this.previous=s,this._delay(function(){this.previous=s,this.selectedItem=i})),!1!==this._trigger("select",e,{item:i})&&this._value(i.value),this.term=this._value(),this.close(e),this.selectedItem=i}}),this.liveRegion=e("",{role:"status","aria-live":"assertive","aria-relevant":"additions"}).addClass("ui-helper-hidden-accessible").appendTo(this.document[0].body),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_destroy:function(){clearTimeout(this.searching),this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete"),this.menu.element.remove(),this.liveRegion.remove()},_setOption:function(e,t){this._super(e,t),"source"===e&&this._initSource(),"appendTo"===e&&this.menu.element.appendTo(this._appendTo()),"disabled"===e&&t&&this.xhr&&this.xhr.abort()},_appendTo:function(){var t=this.options.appendTo;return t&&(t=t.jquery||t.nodeType?e(t):this.document.find(t).eq(0)),t&&t[0]||(t=this.element.closest(".ui-front")),t.length||(t=this.document[0].body),t},_initSource:function(){var t,i,s=this;e.isArray(this.options.source)?(t=this.options.source,this.source=function(i,s){s(e.ui.autocomplete.filter(t,i.term))}):"string"==typeof this.options.source?(i=this.options.source,this.source=function(t,n){s.xhr&&s.xhr.abort(),s.xhr=e.ajax({url:i,data:t,dataType:"json",success:function(e){n(e)},error:function(){n([])}})}):this.source=this.options.source},_searchTimeout:function(e){clearTimeout(this.searching),this.searching=this._delay(function(){var t=this.term===this._value(),i=this.menu.element.is(":visible"),s=e.altKey||e.ctrlKey||e.metaKey||e.shiftKey;(!t||t&&!i&&!s)&&(this.selectedItem=null,this.search(null,e))},this.options.delay)},search:function(e,t){return e=null!=e?e:this._value(),this.term=this._value(),e.length").text(i.label).appendTo(t)},_move:function(e,t){return this.menu.element.is(":visible")?this.menu.isFirstItem()&&/^previous/.test(e)||this.menu.isLastItem()&&/^next/.test(e)?(this.isMultiLine||this._value(this.term),this.menu.blur(),void 0):(this.menu[e](t),void 0):(this.search(null,t),void 0)},widget:function(){return this.menu.element},_value:function(){return this.valueMethod.apply(this.element,arguments)},_keyEvent:function(e,t){(!this.isMultiLine||this.menu.element.is(":visible"))&&(this._move(e,t),t.preventDefault())}}),e.extend(e.ui.autocomplete,{escapeRegex:function(e){return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")},filter:function(t,i){var s=RegExp(e.ui.autocomplete.escapeRegex(i),"i");return e.grep(t,function(e){return s.test(e.label||e.value||e)})}}),e.widget("ui.autocomplete",e.ui.autocomplete,{options:{messages:{noResults:"No search results.",results:function(e){return e+(e>1?" results are":" result is")+" available, use up and down arrow keys to navigate."}}},__response:function(t){var i;this._superApply(arguments),this.options.disabled||this.cancelSearch||(i=t&&t.length?this.options.messages.results(t.length):this.options.messages.noResults,this.liveRegion.children().hide(),e("
      ").text(i).appendTo(this.liveRegion))}}),e.ui.autocomplete;var c,p="ui-button ui-widget ui-state-default ui-corner-all",f="ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",m=function(){var t=e(this);setTimeout(function(){t.find(":ui-button").button("refresh")},1)},g=function(t){var i=t.name,s=t.form,n=e([]);return i&&(i=i.replace(/'/g,"\\'"),n=s?e(s).find("[name='"+i+"'][type=radio]"):e("[name='"+i+"'][type=radio]",t.ownerDocument).filter(function(){return!this.form})),n};e.widget("ui.button",{version:"1.11.4",defaultElement:"").addClass(this._triggerClass).html(a?e("").attr({src:a,alt:n,title:n}):n)),t[r?"before":"after"](i.trigger),i.trigger.click(function(){return e.datepicker._datepickerShowing&&e.datepicker._lastInput===t[0]?e.datepicker._hideDatepicker():e.datepicker._datepickerShowing&&e.datepicker._lastInput!==t[0]?(e.datepicker._hideDatepicker(),e.datepicker._showDatepicker(t[0])):e.datepicker._showDatepicker(t[0]),!1}))},_autoSize:function(e){if(this._get(e,"autoSize")&&!e.inline){var t,i,s,n,a=new Date(2009,11,20),o=this._get(e,"dateFormat");o.match(/[DM]/)&&(t=function(e){for(i=0,s=0,n=0;e.length>n;n++)e[n].length>i&&(i=e[n].length,s=n);return s},a.setMonth(t(this._get(e,o.match(/MM/)?"monthNames":"monthNamesShort"))),a.setDate(t(this._get(e,o.match(/DD/)?"dayNames":"dayNamesShort"))+20-a.getDay())),e.input.attr("size",this._formatDate(e,a).length)}},_inlineDatepicker:function(t,i){var s=e(t);s.hasClass(this.markerClassName)||(s.addClass(this.markerClassName).append(i.dpDiv),e.data(t,"datepicker",i),this._setDate(i,this._getDefaultDate(i),!0),this._updateDatepicker(i),this._updateAlternate(i),i.settings.disabled&&this._disableDatepicker(t),i.dpDiv.css("display","block"))},_dialogDatepicker:function(t,i,s,n,a){var o,h,l,u,d,c=this._dialogInst;return c||(this.uuid+=1,o="dp"+this.uuid,this._dialogInput=e(""),this._dialogInput.keydown(this._doKeyDown),e("body").append(this._dialogInput),c=this._dialogInst=this._newInst(this._dialogInput,!1),c.settings={},e.data(this._dialogInput[0],"datepicker",c)),r(c.settings,n||{}),i=i&&i.constructor===Date?this._formatDate(c,i):i,this._dialogInput.val(i),this._pos=a?a.length?a:[a.pageX,a.pageY]:null,this._pos||(h=document.documentElement.clientWidth,l=document.documentElement.clientHeight,u=document.documentElement.scrollLeft||document.body.scrollLeft,d=document.documentElement.scrollTop||document.body.scrollTop,this._pos=[h/2-100+u,l/2-150+d]),this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px"),c.settings.onSelect=s,this._inDialog=!0,this.dpDiv.addClass(this._dialogClass),this._showDatepicker(this._dialogInput[0]),e.blockUI&&e.blockUI(this.dpDiv),e.data(this._dialogInput[0],"datepicker",c),this},_destroyDatepicker:function(t){var i,s=e(t),n=e.data(t,"datepicker");s.hasClass(this.markerClassName)&&(i=t.nodeName.toLowerCase(),e.removeData(t,"datepicker"),"input"===i?(n.append.remove(),n.trigger.remove(),s.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)):("div"===i||"span"===i)&&s.removeClass(this.markerClassName).empty(),v===n&&(v=null))},_enableDatepicker:function(t){var i,s,n=e(t),a=e.data(t,"datepicker");n.hasClass(this.markerClassName)&&(i=t.nodeName.toLowerCase(),"input"===i?(t.disabled=!1,a.trigger.filter("button").each(function(){this.disabled=!1}).end().filter("img").css({opacity:"1.0",cursor:""})):("div"===i||"span"===i)&&(s=n.children("."+this._inlineClass),s.children().removeClass("ui-state-disabled"),s.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!1)),this._disabledInputs=e.map(this._disabledInputs,function(e){return e===t?null:e}))},_disableDatepicker:function(t){var i,s,n=e(t),a=e.data(t,"datepicker");n.hasClass(this.markerClassName)&&(i=t.nodeName.toLowerCase(),"input"===i?(t.disabled=!0,a.trigger.filter("button").each(function(){this.disabled=!0}).end().filter("img").css({opacity:"0.5",cursor:"default"})):("div"===i||"span"===i)&&(s=n.children("."+this._inlineClass),s.children().addClass("ui-state-disabled"),s.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!0)),this._disabledInputs=e.map(this._disabledInputs,function(e){return e===t?null:e}),this._disabledInputs[this._disabledInputs.length]=t)},_isDisabledDatepicker:function(e){if(!e)return!1;for(var t=0;this._disabledInputs.length>t;t++)if(this._disabledInputs[t]===e)return!0;return!1},_getInst:function(t){try{return e.data(t,"datepicker")}catch(i){throw"Missing instance data for this datepicker"}},_optionDatepicker:function(t,i,s){var n,a,o,h,l=this._getInst(t);return 2===arguments.length&&"string"==typeof i?"defaults"===i?e.extend({},e.datepicker._defaults):l?"all"===i?e.extend({},l.settings):this._get(l,i):null:(n=i||{},"string"==typeof i&&(n={},n[i]=s),l&&(this._curInst===l&&this._hideDatepicker(),a=this._getDateDatepicker(t,!0),o=this._getMinMaxDate(l,"min"),h=this._getMinMaxDate(l,"max"),r(l.settings,n),null!==o&&void 0!==n.dateFormat&&void 0===n.minDate&&(l.settings.minDate=this._formatDate(l,o)),null!==h&&void 0!==n.dateFormat&&void 0===n.maxDate&&(l.settings.maxDate=this._formatDate(l,h)),"disabled"in n&&(n.disabled?this._disableDatepicker(t):this._enableDatepicker(t)),this._attachments(e(t),l),this._autoSize(l),this._setDate(l,a),this._updateAlternate(l),this._updateDatepicker(l)),void 0)},_changeDatepicker:function(e,t,i){this._optionDatepicker(e,t,i)},_refreshDatepicker:function(e){var t=this._getInst(e);t&&this._updateDatepicker(t)},_setDateDatepicker:function(e,t){var i=this._getInst(e);i&&(this._setDate(i,t),this._updateDatepicker(i),this._updateAlternate(i))},_getDateDatepicker:function(e,t){var i=this._getInst(e);return i&&!i.inline&&this._setDateFromField(i,t),i?this._getDate(i):null},_doKeyDown:function(t){var i,s,n,a=e.datepicker._getInst(t.target),o=!0,r=a.dpDiv.is(".ui-datepicker-rtl");if(a._keyEvent=!0,e.datepicker._datepickerShowing)switch(t.keyCode){case 9:e.datepicker._hideDatepicker(),o=!1;break;case 13:return n=e("td."+e.datepicker._dayOverClass+":not(."+e.datepicker._currentClass+")",a.dpDiv),n[0]&&e.datepicker._selectDay(t.target,a.selectedMonth,a.selectedYear,n[0]),i=e.datepicker._get(a,"onSelect"),i?(s=e.datepicker._formatDate(a),i.apply(a.input?a.input[0]:null,[s,a])):e.datepicker._hideDatepicker(),!1;case 27:e.datepicker._hideDatepicker();break;case 33:e.datepicker._adjustDate(t.target,t.ctrlKey?-e.datepicker._get(a,"stepBigMonths"):-e.datepicker._get(a,"stepMonths"),"M");break;case 34:e.datepicker._adjustDate(t.target,t.ctrlKey?+e.datepicker._get(a,"stepBigMonths"):+e.datepicker._get(a,"stepMonths"),"M");break;case 35:(t.ctrlKey||t.metaKey)&&e.datepicker._clearDate(t.target),o=t.ctrlKey||t.metaKey;break;case 36:(t.ctrlKey||t.metaKey)&&e.datepicker._gotoToday(t.target),o=t.ctrlKey||t.metaKey;break;case 37:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,r?1:-1,"D"),o=t.ctrlKey||t.metaKey,t.originalEvent.altKey&&e.datepicker._adjustDate(t.target,t.ctrlKey?-e.datepicker._get(a,"stepBigMonths"):-e.datepicker._get(a,"stepMonths"),"M");break;case 38:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,-7,"D"),o=t.ctrlKey||t.metaKey;break;case 39:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,r?-1:1,"D"),o=t.ctrlKey||t.metaKey,t.originalEvent.altKey&&e.datepicker._adjustDate(t.target,t.ctrlKey?+e.datepicker._get(a,"stepBigMonths"):+e.datepicker._get(a,"stepMonths"),"M");break;case 40:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,7,"D"),o=t.ctrlKey||t.metaKey;break;default:o=!1}else 36===t.keyCode&&t.ctrlKey?e.datepicker._showDatepicker(this):o=!1;o&&(t.preventDefault(),t.stopPropagation())},_doKeyPress:function(t){var i,s,n=e.datepicker._getInst(t.target); +return e.datepicker._get(n,"constrainInput")?(i=e.datepicker._possibleChars(e.datepicker._get(n,"dateFormat")),s=String.fromCharCode(null==t.charCode?t.keyCode:t.charCode),t.ctrlKey||t.metaKey||" ">s||!i||i.indexOf(s)>-1):void 0},_doKeyUp:function(t){var i,s=e.datepicker._getInst(t.target);if(s.input.val()!==s.lastVal)try{i=e.datepicker.parseDate(e.datepicker._get(s,"dateFormat"),s.input?s.input.val():null,e.datepicker._getFormatConfig(s)),i&&(e.datepicker._setDateFromField(s),e.datepicker._updateAlternate(s),e.datepicker._updateDatepicker(s))}catch(n){}return!0},_showDatepicker:function(t){if(t=t.target||t,"input"!==t.nodeName.toLowerCase()&&(t=e("input",t.parentNode)[0]),!e.datepicker._isDisabledDatepicker(t)&&e.datepicker._lastInput!==t){var i,n,a,o,h,l,u;i=e.datepicker._getInst(t),e.datepicker._curInst&&e.datepicker._curInst!==i&&(e.datepicker._curInst.dpDiv.stop(!0,!0),i&&e.datepicker._datepickerShowing&&e.datepicker._hideDatepicker(e.datepicker._curInst.input[0])),n=e.datepicker._get(i,"beforeShow"),a=n?n.apply(t,[t,i]):{},a!==!1&&(r(i.settings,a),i.lastVal=null,e.datepicker._lastInput=t,e.datepicker._setDateFromField(i),e.datepicker._inDialog&&(t.value=""),e.datepicker._pos||(e.datepicker._pos=e.datepicker._findPos(t),e.datepicker._pos[1]+=t.offsetHeight),o=!1,e(t).parents().each(function(){return o|="fixed"===e(this).css("position"),!o}),h={left:e.datepicker._pos[0],top:e.datepicker._pos[1]},e.datepicker._pos=null,i.dpDiv.empty(),i.dpDiv.css({position:"absolute",display:"block",top:"-1000px"}),e.datepicker._updateDatepicker(i),h=e.datepicker._checkOffset(i,h,o),i.dpDiv.css({position:e.datepicker._inDialog&&e.blockUI?"static":o?"fixed":"absolute",display:"none",left:h.left+"px",top:h.top+"px"}),i.inline||(l=e.datepicker._get(i,"showAnim"),u=e.datepicker._get(i,"duration"),i.dpDiv.css("z-index",s(e(t))+1),e.datepicker._datepickerShowing=!0,e.effects&&e.effects.effect[l]?i.dpDiv.show(l,e.datepicker._get(i,"showOptions"),u):i.dpDiv[l||"show"](l?u:null),e.datepicker._shouldFocusInput(i)&&i.input.focus(),e.datepicker._curInst=i))}},_updateDatepicker:function(t){this.maxRows=4,v=t,t.dpDiv.empty().append(this._generateHTML(t)),this._attachHandlers(t);var i,s=this._getNumberOfMonths(t),n=s[1],a=17,r=t.dpDiv.find("."+this._dayOverClass+" a");r.length>0&&o.apply(r.get(0)),t.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""),n>1&&t.dpDiv.addClass("ui-datepicker-multi-"+n).css("width",a*n+"em"),t.dpDiv[(1!==s[0]||1!==s[1]?"add":"remove")+"Class"]("ui-datepicker-multi"),t.dpDiv[(this._get(t,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl"),t===e.datepicker._curInst&&e.datepicker._datepickerShowing&&e.datepicker._shouldFocusInput(t)&&t.input.focus(),t.yearshtml&&(i=t.yearshtml,setTimeout(function(){i===t.yearshtml&&t.yearshtml&&t.dpDiv.find("select.ui-datepicker-year:first").replaceWith(t.yearshtml),i=t.yearshtml=null},0))},_shouldFocusInput:function(e){return e.input&&e.input.is(":visible")&&!e.input.is(":disabled")&&!e.input.is(":focus")},_checkOffset:function(t,i,s){var n=t.dpDiv.outerWidth(),a=t.dpDiv.outerHeight(),o=t.input?t.input.outerWidth():0,r=t.input?t.input.outerHeight():0,h=document.documentElement.clientWidth+(s?0:e(document).scrollLeft()),l=document.documentElement.clientHeight+(s?0:e(document).scrollTop());return i.left-=this._get(t,"isRTL")?n-o:0,i.left-=s&&i.left===t.input.offset().left?e(document).scrollLeft():0,i.top-=s&&i.top===t.input.offset().top+r?e(document).scrollTop():0,i.left-=Math.min(i.left,i.left+n>h&&h>n?Math.abs(i.left+n-h):0),i.top-=Math.min(i.top,i.top+a>l&&l>a?Math.abs(a+r):0),i},_findPos:function(t){for(var i,s=this._getInst(t),n=this._get(s,"isRTL");t&&("hidden"===t.type||1!==t.nodeType||e.expr.filters.hidden(t));)t=t[n?"previousSibling":"nextSibling"];return i=e(t).offset(),[i.left,i.top]},_hideDatepicker:function(t){var i,s,n,a,o=this._curInst;!o||t&&o!==e.data(t,"datepicker")||this._datepickerShowing&&(i=this._get(o,"showAnim"),s=this._get(o,"duration"),n=function(){e.datepicker._tidyDialog(o)},e.effects&&(e.effects.effect[i]||e.effects[i])?o.dpDiv.hide(i,e.datepicker._get(o,"showOptions"),s,n):o.dpDiv["slideDown"===i?"slideUp":"fadeIn"===i?"fadeOut":"hide"](i?s:null,n),i||n(),this._datepickerShowing=!1,a=this._get(o,"onClose"),a&&a.apply(o.input?o.input[0]:null,[o.input?o.input.val():"",o]),this._lastInput=null,this._inDialog&&(this._dialogInput.css({position:"absolute",left:"0",top:"-100px"}),e.blockUI&&(e.unblockUI(),e("body").append(this.dpDiv))),this._inDialog=!1)},_tidyDialog:function(e){e.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(t){if(e.datepicker._curInst){var i=e(t.target),s=e.datepicker._getInst(i[0]);(i[0].id!==e.datepicker._mainDivId&&0===i.parents("#"+e.datepicker._mainDivId).length&&!i.hasClass(e.datepicker.markerClassName)&&!i.closest("."+e.datepicker._triggerClass).length&&e.datepicker._datepickerShowing&&(!e.datepicker._inDialog||!e.blockUI)||i.hasClass(e.datepicker.markerClassName)&&e.datepicker._curInst!==s)&&e.datepicker._hideDatepicker()}},_adjustDate:function(t,i,s){var n=e(t),a=this._getInst(n[0]);this._isDisabledDatepicker(n[0])||(this._adjustInstDate(a,i+("M"===s?this._get(a,"showCurrentAtPos"):0),s),this._updateDatepicker(a))},_gotoToday:function(t){var i,s=e(t),n=this._getInst(s[0]);this._get(n,"gotoCurrent")&&n.currentDay?(n.selectedDay=n.currentDay,n.drawMonth=n.selectedMonth=n.currentMonth,n.drawYear=n.selectedYear=n.currentYear):(i=new Date,n.selectedDay=i.getDate(),n.drawMonth=n.selectedMonth=i.getMonth(),n.drawYear=n.selectedYear=i.getFullYear()),this._notifyChange(n),this._adjustDate(s)},_selectMonthYear:function(t,i,s){var n=e(t),a=this._getInst(n[0]);a["selected"+("M"===s?"Month":"Year")]=a["draw"+("M"===s?"Month":"Year")]=parseInt(i.options[i.selectedIndex].value,10),this._notifyChange(a),this._adjustDate(n)},_selectDay:function(t,i,s,n){var a,o=e(t);e(n).hasClass(this._unselectableClass)||this._isDisabledDatepicker(o[0])||(a=this._getInst(o[0]),a.selectedDay=a.currentDay=e("a",n).html(),a.selectedMonth=a.currentMonth=i,a.selectedYear=a.currentYear=s,this._selectDate(t,this._formatDate(a,a.currentDay,a.currentMonth,a.currentYear)))},_clearDate:function(t){var i=e(t);this._selectDate(i,"")},_selectDate:function(t,i){var s,n=e(t),a=this._getInst(n[0]);i=null!=i?i:this._formatDate(a),a.input&&a.input.val(i),this._updateAlternate(a),s=this._get(a,"onSelect"),s?s.apply(a.input?a.input[0]:null,[i,a]):a.input&&a.input.trigger("change"),a.inline?this._updateDatepicker(a):(this._hideDatepicker(),this._lastInput=a.input[0],"object"!=typeof a.input[0]&&a.input.focus(),this._lastInput=null)},_updateAlternate:function(t){var i,s,n,a=this._get(t,"altField");a&&(i=this._get(t,"altFormat")||this._get(t,"dateFormat"),s=this._getDate(t),n=this.formatDate(i,s,this._getFormatConfig(t)),e(a).each(function(){e(this).val(n)}))},noWeekends:function(e){var t=e.getDay();return[t>0&&6>t,""]},iso8601Week:function(e){var t,i=new Date(e.getTime());return i.setDate(i.getDate()+4-(i.getDay()||7)),t=i.getTime(),i.setMonth(0),i.setDate(1),Math.floor(Math.round((t-i)/864e5)/7)+1},parseDate:function(t,i,s){if(null==t||null==i)throw"Invalid arguments";if(i="object"==typeof i?""+i:i+"",""===i)return null;var n,a,o,r,h=0,l=(s?s.shortYearCutoff:null)||this._defaults.shortYearCutoff,u="string"!=typeof l?l:(new Date).getFullYear()%100+parseInt(l,10),d=(s?s.dayNamesShort:null)||this._defaults.dayNamesShort,c=(s?s.dayNames:null)||this._defaults.dayNames,p=(s?s.monthNamesShort:null)||this._defaults.monthNamesShort,f=(s?s.monthNames:null)||this._defaults.monthNames,m=-1,g=-1,v=-1,y=-1,b=!1,_=function(e){var i=t.length>n+1&&t.charAt(n+1)===e;return i&&n++,i},x=function(e){var t=_(e),s="@"===e?14:"!"===e?20:"y"===e&&t?4:"o"===e?3:2,n="y"===e?s:1,a=RegExp("^\\d{"+n+","+s+"}"),o=i.substring(h).match(a);if(!o)throw"Missing number at position "+h;return h+=o[0].length,parseInt(o[0],10)},w=function(t,s,n){var a=-1,o=e.map(_(t)?n:s,function(e,t){return[[t,e]]}).sort(function(e,t){return-(e[1].length-t[1].length)});if(e.each(o,function(e,t){var s=t[1];return i.substr(h,s.length).toLowerCase()===s.toLowerCase()?(a=t[0],h+=s.length,!1):void 0}),-1!==a)return a+1;throw"Unknown name at position "+h},k=function(){if(i.charAt(h)!==t.charAt(n))throw"Unexpected literal at position "+h;h++};for(n=0;t.length>n;n++)if(b)"'"!==t.charAt(n)||_("'")?k():b=!1;else switch(t.charAt(n)){case"d":v=x("d");break;case"D":w("D",d,c);break;case"o":y=x("o");break;case"m":g=x("m");break;case"M":g=w("M",p,f);break;case"y":m=x("y");break;case"@":r=new Date(x("@")),m=r.getFullYear(),g=r.getMonth()+1,v=r.getDate();break;case"!":r=new Date((x("!")-this._ticksTo1970)/1e4),m=r.getFullYear(),g=r.getMonth()+1,v=r.getDate();break;case"'":_("'")?k():b=!0;break;default:k()}if(i.length>h&&(o=i.substr(h),!/^\s+/.test(o)))throw"Extra/unparsed characters found in date: "+o;if(-1===m?m=(new Date).getFullYear():100>m&&(m+=(new Date).getFullYear()-(new Date).getFullYear()%100+(u>=m?0:-100)),y>-1)for(g=1,v=y;;){if(a=this._getDaysInMonth(m,g-1),a>=v)break;g++,v-=a}if(r=this._daylightSavingAdjust(new Date(m,g-1,v)),r.getFullYear()!==m||r.getMonth()+1!==g||r.getDate()!==v)throw"Invalid date";return r},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:1e7*60*60*24*(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925)),formatDate:function(e,t,i){if(!t)return"";var s,n=(i?i.dayNamesShort:null)||this._defaults.dayNamesShort,a=(i?i.dayNames:null)||this._defaults.dayNames,o=(i?i.monthNamesShort:null)||this._defaults.monthNamesShort,r=(i?i.monthNames:null)||this._defaults.monthNames,h=function(t){var i=e.length>s+1&&e.charAt(s+1)===t;return i&&s++,i},l=function(e,t,i){var s=""+t;if(h(e))for(;i>s.length;)s="0"+s;return s},u=function(e,t,i,s){return h(e)?s[t]:i[t]},d="",c=!1;if(t)for(s=0;e.length>s;s++)if(c)"'"!==e.charAt(s)||h("'")?d+=e.charAt(s):c=!1;else switch(e.charAt(s)){case"d":d+=l("d",t.getDate(),2);break;case"D":d+=u("D",t.getDay(),n,a);break;case"o":d+=l("o",Math.round((new Date(t.getFullYear(),t.getMonth(),t.getDate()).getTime()-new Date(t.getFullYear(),0,0).getTime())/864e5),3);break;case"m":d+=l("m",t.getMonth()+1,2);break;case"M":d+=u("M",t.getMonth(),o,r);break;case"y":d+=h("y")?t.getFullYear():(10>t.getYear()%100?"0":"")+t.getYear()%100;break;case"@":d+=t.getTime();break;case"!":d+=1e4*t.getTime()+this._ticksTo1970;break;case"'":h("'")?d+="'":c=!0;break;default:d+=e.charAt(s)}return d},_possibleChars:function(e){var t,i="",s=!1,n=function(i){var s=e.length>t+1&&e.charAt(t+1)===i;return s&&t++,s};for(t=0;e.length>t;t++)if(s)"'"!==e.charAt(t)||n("'")?i+=e.charAt(t):s=!1;else switch(e.charAt(t)){case"d":case"m":case"y":case"@":i+="0123456789";break;case"D":case"M":return null;case"'":n("'")?i+="'":s=!0;break;default:i+=e.charAt(t)}return i},_get:function(e,t){return void 0!==e.settings[t]?e.settings[t]:this._defaults[t]},_setDateFromField:function(e,t){if(e.input.val()!==e.lastVal){var i=this._get(e,"dateFormat"),s=e.lastVal=e.input?e.input.val():null,n=this._getDefaultDate(e),a=n,o=this._getFormatConfig(e);try{a=this.parseDate(i,s,o)||n}catch(r){s=t?"":s}e.selectedDay=a.getDate(),e.drawMonth=e.selectedMonth=a.getMonth(),e.drawYear=e.selectedYear=a.getFullYear(),e.currentDay=s?a.getDate():0,e.currentMonth=s?a.getMonth():0,e.currentYear=s?a.getFullYear():0,this._adjustInstDate(e)}},_getDefaultDate:function(e){return this._restrictMinMax(e,this._determineDate(e,this._get(e,"defaultDate"),new Date))},_determineDate:function(t,i,s){var n=function(e){var t=new Date;return t.setDate(t.getDate()+e),t},a=function(i){try{return e.datepicker.parseDate(e.datepicker._get(t,"dateFormat"),i,e.datepicker._getFormatConfig(t))}catch(s){}for(var n=(i.toLowerCase().match(/^c/)?e.datepicker._getDate(t):null)||new Date,a=n.getFullYear(),o=n.getMonth(),r=n.getDate(),h=/([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,l=h.exec(i);l;){switch(l[2]||"d"){case"d":case"D":r+=parseInt(l[1],10);break;case"w":case"W":r+=7*parseInt(l[1],10);break;case"m":case"M":o+=parseInt(l[1],10),r=Math.min(r,e.datepicker._getDaysInMonth(a,o));break;case"y":case"Y":a+=parseInt(l[1],10),r=Math.min(r,e.datepicker._getDaysInMonth(a,o))}l=h.exec(i)}return new Date(a,o,r)},o=null==i||""===i?s:"string"==typeof i?a(i):"number"==typeof i?isNaN(i)?s:n(i):new Date(i.getTime());return o=o&&"Invalid Date"==""+o?s:o,o&&(o.setHours(0),o.setMinutes(0),o.setSeconds(0),o.setMilliseconds(0)),this._daylightSavingAdjust(o)},_daylightSavingAdjust:function(e){return e?(e.setHours(e.getHours()>12?e.getHours()+2:0),e):null},_setDate:function(e,t,i){var s=!t,n=e.selectedMonth,a=e.selectedYear,o=this._restrictMinMax(e,this._determineDate(e,t,new Date));e.selectedDay=e.currentDay=o.getDate(),e.drawMonth=e.selectedMonth=e.currentMonth=o.getMonth(),e.drawYear=e.selectedYear=e.currentYear=o.getFullYear(),n===e.selectedMonth&&a===e.selectedYear||i||this._notifyChange(e),this._adjustInstDate(e),e.input&&e.input.val(s?"":this._formatDate(e))},_getDate:function(e){var t=!e.currentYear||e.input&&""===e.input.val()?null:this._daylightSavingAdjust(new Date(e.currentYear,e.currentMonth,e.currentDay));return t},_attachHandlers:function(t){var i=this._get(t,"stepMonths"),s="#"+t.id.replace(/\\\\/g,"\\");t.dpDiv.find("[data-handler]").map(function(){var t={prev:function(){e.datepicker._adjustDate(s,-i,"M")},next:function(){e.datepicker._adjustDate(s,+i,"M")},hide:function(){e.datepicker._hideDatepicker()},today:function(){e.datepicker._gotoToday(s)},selectDay:function(){return e.datepicker._selectDay(s,+this.getAttribute("data-month"),+this.getAttribute("data-year"),this),!1},selectMonth:function(){return e.datepicker._selectMonthYear(s,this,"M"),!1},selectYear:function(){return e.datepicker._selectMonthYear(s,this,"Y"),!1}};e(this).bind(this.getAttribute("data-event"),t[this.getAttribute("data-handler")])})},_generateHTML:function(e){var t,i,s,n,a,o,r,h,l,u,d,c,p,f,m,g,v,y,b,_,x,w,k,T,D,S,M,C,N,A,P,I,H,z,F,E,O,j,W,L=new Date,R=this._daylightSavingAdjust(new Date(L.getFullYear(),L.getMonth(),L.getDate())),Y=this._get(e,"isRTL"),B=this._get(e,"showButtonPanel"),J=this._get(e,"hideIfNoPrevNext"),q=this._get(e,"navigationAsDateFormat"),K=this._getNumberOfMonths(e),V=this._get(e,"showCurrentAtPos"),U=this._get(e,"stepMonths"),Q=1!==K[0]||1!==K[1],G=this._daylightSavingAdjust(e.currentDay?new Date(e.currentYear,e.currentMonth,e.currentDay):new Date(9999,9,9)),X=this._getMinMaxDate(e,"min"),$=this._getMinMaxDate(e,"max"),Z=e.drawMonth-V,et=e.drawYear;if(0>Z&&(Z+=12,et--),$)for(t=this._daylightSavingAdjust(new Date($.getFullYear(),$.getMonth()-K[0]*K[1]+1,$.getDate())),t=X&&X>t?X:t;this._daylightSavingAdjust(new Date(et,Z,1))>t;)Z--,0>Z&&(Z=11,et--);for(e.drawMonth=Z,e.drawYear=et,i=this._get(e,"prevText"),i=q?this.formatDate(i,this._daylightSavingAdjust(new Date(et,Z-U,1)),this._getFormatConfig(e)):i,s=this._canAdjustMonth(e,-1,et,Z)?""+i+"":J?"":""+i+"",n=this._get(e,"nextText"),n=q?this.formatDate(n,this._daylightSavingAdjust(new Date(et,Z+U,1)),this._getFormatConfig(e)):n,a=this._canAdjustMonth(e,1,et,Z)?""+n+"":J?"":""+n+"",o=this._get(e,"currentText"),r=this._get(e,"gotoCurrent")&&e.currentDay?G:R,o=q?this.formatDate(o,r,this._getFormatConfig(e)):o,h=e.inline?"":"",l=B?"
      "+(Y?h:"")+(this._isInRange(e,r)?"":"")+(Y?"":h)+"
      ":"",u=parseInt(this._get(e,"firstDay"),10),u=isNaN(u)?0:u,d=this._get(e,"showWeek"),c=this._get(e,"dayNames"),p=this._get(e,"dayNamesMin"),f=this._get(e,"monthNames"),m=this._get(e,"monthNamesShort"),g=this._get(e,"beforeShowDay"),v=this._get(e,"showOtherMonths"),y=this._get(e,"selectOtherMonths"),b=this._getDefaultDate(e),_="",w=0;K[0]>w;w++){for(k="",this.maxRows=4,T=0;K[1]>T;T++){if(D=this._daylightSavingAdjust(new Date(et,Z,e.selectedDay)),S=" ui-corner-all",M="",Q){if(M+="
      "}for(M+="
      "+(/all|left/.test(S)&&0===w?Y?a:s:"")+(/all|right/.test(S)&&0===w?Y?s:a:"")+this._generateMonthYearHeader(e,Z,et,X,$,w>0||T>0,f,m)+"
      "+"",C=d?"":"",x=0;7>x;x++)N=(x+u)%7,C+="";for(M+=C+"",A=this._getDaysInMonth(et,Z),et===e.selectedYear&&Z===e.selectedMonth&&(e.selectedDay=Math.min(e.selectedDay,A)),P=(this._getFirstDayOfMonth(et,Z)-u+7)%7,I=Math.ceil((P+A)/7),H=Q?this.maxRows>I?this.maxRows:I:I,this.maxRows=H,z=this._daylightSavingAdjust(new Date(et,Z,1-P)),F=0;H>F;F++){for(M+="",E=d?"":"",x=0;7>x;x++)O=g?g.apply(e.input?e.input[0]:null,[z]):[!0,""],j=z.getMonth()!==Z,W=j&&!y||!O[0]||X&&X>z||$&&z>$,E+="",z.setDate(z.getDate()+1),z=this._daylightSavingAdjust(z);M+=E+""}Z++,Z>11&&(Z=0,et++),M+="
      "+this._get(e,"weekHeader")+"=5?" class='ui-datepicker-week-end'":"")+">"+""+p[N]+"
      "+this._get(e,"calculateWeek")(z)+""+(j&&!v?" ":W?""+z.getDate()+"":""+z.getDate()+"")+"
      "+(Q?"
      "+(K[0]>0&&T===K[1]-1?"
      ":""):""),k+=M}_+=k}return _+=l,e._keyEvent=!1,_},_generateMonthYearHeader:function(e,t,i,s,n,a,o,r){var h,l,u,d,c,p,f,m,g=this._get(e,"changeMonth"),v=this._get(e,"changeYear"),y=this._get(e,"showMonthAfterYear"),b="
      ",_="";if(a||!g)_+=""+o[t]+"";else{for(h=s&&s.getFullYear()===i,l=n&&n.getFullYear()===i,_+=""}if(y||(b+=_+(!a&&g&&v?"":" ")),!e.yearshtml)if(e.yearshtml="",a||!v)b+=""+i+"";else{for(d=this._get(e,"yearRange").split(":"),c=(new Date).getFullYear(),p=function(e){var t=e.match(/c[+\-].*/)?i+parseInt(e.substring(1),10):e.match(/[+\-].*/)?c+parseInt(e,10):parseInt(e,10);return isNaN(t)?c:t},f=p(d[0]),m=Math.max(f,p(d[1]||"")),f=s?Math.max(f,s.getFullYear()):f,m=n?Math.min(m,n.getFullYear()):m,e.yearshtml+="",b+=e.yearshtml,e.yearshtml=null}return b+=this._get(e,"yearSuffix"),y&&(b+=(!a&&g&&v?"":" ")+_),b+="
      "},_adjustInstDate:function(e,t,i){var s=e.drawYear+("Y"===i?t:0),n=e.drawMonth+("M"===i?t:0),a=Math.min(e.selectedDay,this._getDaysInMonth(s,n))+("D"===i?t:0),o=this._restrictMinMax(e,this._daylightSavingAdjust(new Date(s,n,a)));e.selectedDay=o.getDate(),e.drawMonth=e.selectedMonth=o.getMonth(),e.drawYear=e.selectedYear=o.getFullYear(),("M"===i||"Y"===i)&&this._notifyChange(e)},_restrictMinMax:function(e,t){var i=this._getMinMaxDate(e,"min"),s=this._getMinMaxDate(e,"max"),n=i&&i>t?i:t;return s&&n>s?s:n},_notifyChange:function(e){var t=this._get(e,"onChangeMonthYear");t&&t.apply(e.input?e.input[0]:null,[e.selectedYear,e.selectedMonth+1,e])},_getNumberOfMonths:function(e){var t=this._get(e,"numberOfMonths");return null==t?[1,1]:"number"==typeof t?[1,t]:t},_getMinMaxDate:function(e,t){return this._determineDate(e,this._get(e,t+"Date"),null)},_getDaysInMonth:function(e,t){return 32-this._daylightSavingAdjust(new Date(e,t,32)).getDate()},_getFirstDayOfMonth:function(e,t){return new Date(e,t,1).getDay()},_canAdjustMonth:function(e,t,i,s){var n=this._getNumberOfMonths(e),a=this._daylightSavingAdjust(new Date(i,s+(0>t?t:n[0]*n[1]),1));return 0>t&&a.setDate(this._getDaysInMonth(a.getFullYear(),a.getMonth())),this._isInRange(e,a)},_isInRange:function(e,t){var i,s,n=this._getMinMaxDate(e,"min"),a=this._getMinMaxDate(e,"max"),o=null,r=null,h=this._get(e,"yearRange");return h&&(i=h.split(":"),s=(new Date).getFullYear(),o=parseInt(i[0],10),r=parseInt(i[1],10),i[0].match(/[+\-].*/)&&(o+=s),i[1].match(/[+\-].*/)&&(r+=s)),(!n||t.getTime()>=n.getTime())&&(!a||t.getTime()<=a.getTime())&&(!o||t.getFullYear()>=o)&&(!r||r>=t.getFullYear())},_getFormatConfig:function(e){var t=this._get(e,"shortYearCutoff");return t="string"!=typeof t?t:(new Date).getFullYear()%100+parseInt(t,10),{shortYearCutoff:t,dayNamesShort:this._get(e,"dayNamesShort"),dayNames:this._get(e,"dayNames"),monthNamesShort:this._get(e,"monthNamesShort"),monthNames:this._get(e,"monthNames")}},_formatDate:function(e,t,i,s){t||(e.currentDay=e.selectedDay,e.currentMonth=e.selectedMonth,e.currentYear=e.selectedYear);var n=t?"object"==typeof t?t:this._daylightSavingAdjust(new Date(s,i,t)):this._daylightSavingAdjust(new Date(e.currentYear,e.currentMonth,e.currentDay));return this.formatDate(this._get(e,"dateFormat"),n,this._getFormatConfig(e))}}),e.fn.datepicker=function(t){if(!this.length)return this;e.datepicker.initialized||(e(document).mousedown(e.datepicker._checkExternalClick),e.datepicker.initialized=!0),0===e("#"+e.datepicker._mainDivId).length&&e("body").append(e.datepicker.dpDiv);var i=Array.prototype.slice.call(arguments,1);return"string"!=typeof t||"isDisabled"!==t&&"getDate"!==t&&"widget"!==t?"option"===t&&2===arguments.length&&"string"==typeof arguments[1]?e.datepicker["_"+t+"Datepicker"].apply(e.datepicker,[this[0]].concat(i)):this.each(function(){"string"==typeof t?e.datepicker["_"+t+"Datepicker"].apply(e.datepicker,[this].concat(i)):e.datepicker._attachDatepicker(this,t)}):e.datepicker["_"+t+"Datepicker"].apply(e.datepicker,[this[0]].concat(i))},e.datepicker=new n,e.datepicker.initialized=!1,e.datepicker.uuid=(new Date).getTime(),e.datepicker.version="1.11.4",e.datepicker,e.widget("ui.draggable",e.ui.mouse,{version:"1.11.4",widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1,drag:null,start:null,stop:null},_create:function(){"original"===this.options.helper&&this._setPositionRelative(),this.options.addClasses&&this.element.addClass("ui-draggable"),this.options.disabled&&this.element.addClass("ui-draggable-disabled"),this._setHandleClassName(),this._mouseInit()},_setOption:function(e,t){this._super(e,t),"handle"===e&&(this._removeHandleClassName(),this._setHandleClassName())},_destroy:function(){return(this.helper||this.element).is(".ui-draggable-dragging")?(this.destroyOnClear=!0,void 0):(this.element.removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled"),this._removeHandleClassName(),this._mouseDestroy(),void 0)},_mouseCapture:function(t){var i=this.options;return this._blurActiveElement(t),this.helper||i.disabled||e(t.target).closest(".ui-resizable-handle").length>0?!1:(this.handle=this._getHandle(t),this.handle?(this._blockFrames(i.iframeFix===!0?"iframe":i.iframeFix),!0):!1)},_blockFrames:function(t){this.iframeBlocks=this.document.find(t).map(function(){var t=e(this);return e("
      ").css("position","absolute").appendTo(t.parent()).outerWidth(t.outerWidth()).outerHeight(t.outerHeight()).offset(t.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_blurActiveElement:function(t){var i=this.document[0];if(this.handleElement.is(t.target))try{i.activeElement&&"body"!==i.activeElement.nodeName.toLowerCase()&&e(i.activeElement).blur()}catch(s){}},_mouseStart:function(t){var i=this.options;return this.helper=this._createHelper(t),this.helper.addClass("ui-draggable-dragging"),this._cacheHelperProportions(),e.ui.ddmanager&&(e.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(!0),this.offsetParent=this.helper.offsetParent(),this.hasFixedAncestor=this.helper.parents().filter(function(){return"fixed"===e(this).css("position")}).length>0,this.positionAbs=this.element.offset(),this._refreshOffsets(t),this.originalPosition=this.position=this._generatePosition(t,!1),this.originalPageX=t.pageX,this.originalPageY=t.pageY,i.cursorAt&&this._adjustOffsetFromHelper(i.cursorAt),this._setContainment(),this._trigger("start",t)===!1?(this._clear(),!1):(this._cacheHelperProportions(),e.ui.ddmanager&&!i.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this._normalizeRightBottom(),this._mouseDrag(t,!0),e.ui.ddmanager&&e.ui.ddmanager.dragStart(this,t),!0)},_refreshOffsets:function(e){this.offset={top:this.positionAbs.top-this.margins.top,left:this.positionAbs.left-this.margins.left,scroll:!1,parent:this._getParentOffset(),relative:this._getRelativeOffset()},this.offset.click={left:e.pageX-this.offset.left,top:e.pageY-this.offset.top}},_mouseDrag:function(t,i){if(this.hasFixedAncestor&&(this.offset.parent=this._getParentOffset()),this.position=this._generatePosition(t,!0),this.positionAbs=this._convertPositionTo("absolute"),!i){var s=this._uiHash();if(this._trigger("drag",t,s)===!1)return this._mouseUp({}),!1;this.position=s.position}return this.helper[0].style.left=this.position.left+"px",this.helper[0].style.top=this.position.top+"px",e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),!1},_mouseStop:function(t){var i=this,s=!1;return e.ui.ddmanager&&!this.options.dropBehaviour&&(s=e.ui.ddmanager.drop(this,t)),this.dropped&&(s=this.dropped,this.dropped=!1),"invalid"===this.options.revert&&!s||"valid"===this.options.revert&&s||this.options.revert===!0||e.isFunction(this.options.revert)&&this.options.revert.call(this.element,s)?e(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){i._trigger("stop",t)!==!1&&i._clear()}):this._trigger("stop",t)!==!1&&this._clear(),!1},_mouseUp:function(t){return this._unblockFrames(),e.ui.ddmanager&&e.ui.ddmanager.dragStop(this,t),this.handleElement.is(t.target)&&this.element.focus(),e.ui.mouse.prototype._mouseUp.call(this,t)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear(),this},_getHandle:function(t){return this.options.handle?!!e(t.target).closest(this.element.find(this.options.handle)).length:!0},_setHandleClassName:function(){this.handleElement=this.options.handle?this.element.find(this.options.handle):this.element,this.handleElement.addClass("ui-draggable-handle")},_removeHandleClassName:function(){this.handleElement.removeClass("ui-draggable-handle")},_createHelper:function(t){var i=this.options,s=e.isFunction(i.helper),n=s?e(i.helper.apply(this.element[0],[t])):"clone"===i.helper?this.element.clone().removeAttr("id"):this.element;return n.parents("body").length||n.appendTo("parent"===i.appendTo?this.element[0].parentNode:i.appendTo),s&&n[0]===this.element[0]&&this._setPositionRelative(),n[0]===this.element[0]||/(fixed|absolute)/.test(n.css("position"))||n.css("position","absolute"),n},_setPositionRelative:function(){/^(?:r|a|f)/.test(this.element.css("position"))||(this.element[0].style.position="relative")},_adjustOffsetFromHelper:function(t){"string"==typeof t&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_isRootNode:function(e){return/(html|body)/i.test(e.tagName)||e===this.document[0]},_getParentOffset:function(){var t=this.offsetParent.offset(),i=this.document[0];return"absolute"===this.cssPosition&&this.scrollParent[0]!==i&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop()),this._isRootNode(this.offsetParent[0])&&(t={top:0,left:0}),{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"!==this.cssPosition)return{top:0,left:0};var e=this.element.position(),t=this._isRootNode(this.scrollParent[0]);return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+(t?0:this.scrollParent.scrollTop()),left:e.left-(parseInt(this.helper.css("left"),10)||0)+(t?0:this.scrollParent.scrollLeft())}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t,i,s,n=this.options,a=this.document[0];return this.relativeContainer=null,n.containment?"window"===n.containment?(this.containment=[e(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,e(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,e(window).scrollLeft()+e(window).width()-this.helperProportions.width-this.margins.left,e(window).scrollTop()+(e(window).height()||a.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],void 0):"document"===n.containment?(this.containment=[0,0,e(a).width()-this.helperProportions.width-this.margins.left,(e(a).height()||a.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],void 0):n.containment.constructor===Array?(this.containment=n.containment,void 0):("parent"===n.containment&&(n.containment=this.helper[0].parentNode),i=e(n.containment),s=i[0],s&&(t=/(scroll|auto)/.test(i.css("overflow")),this.containment=[(parseInt(i.css("borderLeftWidth"),10)||0)+(parseInt(i.css("paddingLeft"),10)||0),(parseInt(i.css("borderTopWidth"),10)||0)+(parseInt(i.css("paddingTop"),10)||0),(t?Math.max(s.scrollWidth,s.offsetWidth):s.offsetWidth)-(parseInt(i.css("borderRightWidth"),10)||0)-(parseInt(i.css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(t?Math.max(s.scrollHeight,s.offsetHeight):s.offsetHeight)-(parseInt(i.css("borderBottomWidth"),10)||0)-(parseInt(i.css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relativeContainer=i),void 0):(this.containment=null,void 0) +},_convertPositionTo:function(e,t){t||(t=this.position);var i="absolute"===e?1:-1,s=this._isRootNode(this.scrollParent[0]);return{top:t.top+this.offset.relative.top*i+this.offset.parent.top*i-("fixed"===this.cssPosition?-this.offset.scroll.top:s?0:this.offset.scroll.top)*i,left:t.left+this.offset.relative.left*i+this.offset.parent.left*i-("fixed"===this.cssPosition?-this.offset.scroll.left:s?0:this.offset.scroll.left)*i}},_generatePosition:function(e,t){var i,s,n,a,o=this.options,r=this._isRootNode(this.scrollParent[0]),h=e.pageX,l=e.pageY;return r&&this.offset.scroll||(this.offset.scroll={top:this.scrollParent.scrollTop(),left:this.scrollParent.scrollLeft()}),t&&(this.containment&&(this.relativeContainer?(s=this.relativeContainer.offset(),i=[this.containment[0]+s.left,this.containment[1]+s.top,this.containment[2]+s.left,this.containment[3]+s.top]):i=this.containment,e.pageX-this.offset.click.lefti[2]&&(h=i[2]+this.offset.click.left),e.pageY-this.offset.click.top>i[3]&&(l=i[3]+this.offset.click.top)),o.grid&&(n=o.grid[1]?this.originalPageY+Math.round((l-this.originalPageY)/o.grid[1])*o.grid[1]:this.originalPageY,l=i?n-this.offset.click.top>=i[1]||n-this.offset.click.top>i[3]?n:n-this.offset.click.top>=i[1]?n-o.grid[1]:n+o.grid[1]:n,a=o.grid[0]?this.originalPageX+Math.round((h-this.originalPageX)/o.grid[0])*o.grid[0]:this.originalPageX,h=i?a-this.offset.click.left>=i[0]||a-this.offset.click.left>i[2]?a:a-this.offset.click.left>=i[0]?a-o.grid[0]:a+o.grid[0]:a),"y"===o.axis&&(h=this.originalPageX),"x"===o.axis&&(l=this.originalPageY)),{top:l-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.offset.scroll.top:r?0:this.offset.scroll.top),left:h-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.offset.scroll.left:r?0:this.offset.scroll.left)}},_clear:function(){this.helper.removeClass("ui-draggable-dragging"),this.helper[0]===this.element[0]||this.cancelHelperRemoval||this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1,this.destroyOnClear&&this.destroy()},_normalizeRightBottom:function(){"y"!==this.options.axis&&"auto"!==this.helper.css("right")&&(this.helper.width(this.helper.width()),this.helper.css("right","auto")),"x"!==this.options.axis&&"auto"!==this.helper.css("bottom")&&(this.helper.height(this.helper.height()),this.helper.css("bottom","auto"))},_trigger:function(t,i,s){return s=s||this._uiHash(),e.ui.plugin.call(this,t,[i,s,this],!0),/^(drag|start|stop)/.test(t)&&(this.positionAbs=this._convertPositionTo("absolute"),s.offset=this.positionAbs),e.Widget.prototype._trigger.call(this,t,i,s)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),e.ui.plugin.add("draggable","connectToSortable",{start:function(t,i,s){var n=e.extend({},i,{item:s.element});s.sortables=[],e(s.options.connectToSortable).each(function(){var i=e(this).sortable("instance");i&&!i.options.disabled&&(s.sortables.push(i),i.refreshPositions(),i._trigger("activate",t,n))})},stop:function(t,i,s){var n=e.extend({},i,{item:s.element});s.cancelHelperRemoval=!1,e.each(s.sortables,function(){var e=this;e.isOver?(e.isOver=0,s.cancelHelperRemoval=!0,e.cancelHelperRemoval=!1,e._storedCSS={position:e.placeholder.css("position"),top:e.placeholder.css("top"),left:e.placeholder.css("left")},e._mouseStop(t),e.options.helper=e.options._helper):(e.cancelHelperRemoval=!0,e._trigger("deactivate",t,n))})},drag:function(t,i,s){e.each(s.sortables,function(){var n=!1,a=this;a.positionAbs=s.positionAbs,a.helperProportions=s.helperProportions,a.offset.click=s.offset.click,a._intersectsWith(a.containerCache)&&(n=!0,e.each(s.sortables,function(){return this.positionAbs=s.positionAbs,this.helperProportions=s.helperProportions,this.offset.click=s.offset.click,this!==a&&this._intersectsWith(this.containerCache)&&e.contains(a.element[0],this.element[0])&&(n=!1),n})),n?(a.isOver||(a.isOver=1,s._parent=i.helper.parent(),a.currentItem=i.helper.appendTo(a.element).data("ui-sortable-item",!0),a.options._helper=a.options.helper,a.options.helper=function(){return i.helper[0]},t.target=a.currentItem[0],a._mouseCapture(t,!0),a._mouseStart(t,!0,!0),a.offset.click.top=s.offset.click.top,a.offset.click.left=s.offset.click.left,a.offset.parent.left-=s.offset.parent.left-a.offset.parent.left,a.offset.parent.top-=s.offset.parent.top-a.offset.parent.top,s._trigger("toSortable",t),s.dropped=a.element,e.each(s.sortables,function(){this.refreshPositions()}),s.currentItem=s.element,a.fromOutside=s),a.currentItem&&(a._mouseDrag(t),i.position=a.position)):a.isOver&&(a.isOver=0,a.cancelHelperRemoval=!0,a.options._revert=a.options.revert,a.options.revert=!1,a._trigger("out",t,a._uiHash(a)),a._mouseStop(t,!0),a.options.revert=a.options._revert,a.options.helper=a.options._helper,a.placeholder&&a.placeholder.remove(),i.helper.appendTo(s._parent),s._refreshOffsets(t),i.position=s._generatePosition(t,!0),s._trigger("fromSortable",t),s.dropped=!1,e.each(s.sortables,function(){this.refreshPositions()}))})}}),e.ui.plugin.add("draggable","cursor",{start:function(t,i,s){var n=e("body"),a=s.options;n.css("cursor")&&(a._cursor=n.css("cursor")),n.css("cursor",a.cursor)},stop:function(t,i,s){var n=s.options;n._cursor&&e("body").css("cursor",n._cursor)}}),e.ui.plugin.add("draggable","opacity",{start:function(t,i,s){var n=e(i.helper),a=s.options;n.css("opacity")&&(a._opacity=n.css("opacity")),n.css("opacity",a.opacity)},stop:function(t,i,s){var n=s.options;n._opacity&&e(i.helper).css("opacity",n._opacity)}}),e.ui.plugin.add("draggable","scroll",{start:function(e,t,i){i.scrollParentNotHidden||(i.scrollParentNotHidden=i.helper.scrollParent(!1)),i.scrollParentNotHidden[0]!==i.document[0]&&"HTML"!==i.scrollParentNotHidden[0].tagName&&(i.overflowOffset=i.scrollParentNotHidden.offset())},drag:function(t,i,s){var n=s.options,a=!1,o=s.scrollParentNotHidden[0],r=s.document[0];o!==r&&"HTML"!==o.tagName?(n.axis&&"x"===n.axis||(s.overflowOffset.top+o.offsetHeight-t.pageY=0;c--)h=s.snapElements[c].left-s.margins.left,l=h+s.snapElements[c].width,u=s.snapElements[c].top-s.margins.top,d=u+s.snapElements[c].height,h-m>v||g>l+m||u-m>b||y>d+m||!e.contains(s.snapElements[c].item.ownerDocument,s.snapElements[c].item)?(s.snapElements[c].snapping&&s.options.snap.release&&s.options.snap.release.call(s.element,t,e.extend(s._uiHash(),{snapItem:s.snapElements[c].item})),s.snapElements[c].snapping=!1):("inner"!==f.snapMode&&(n=m>=Math.abs(u-b),a=m>=Math.abs(d-y),o=m>=Math.abs(h-v),r=m>=Math.abs(l-g),n&&(i.position.top=s._convertPositionTo("relative",{top:u-s.helperProportions.height,left:0}).top),a&&(i.position.top=s._convertPositionTo("relative",{top:d,left:0}).top),o&&(i.position.left=s._convertPositionTo("relative",{top:0,left:h-s.helperProportions.width}).left),r&&(i.position.left=s._convertPositionTo("relative",{top:0,left:l}).left)),p=n||a||o||r,"outer"!==f.snapMode&&(n=m>=Math.abs(u-y),a=m>=Math.abs(d-b),o=m>=Math.abs(h-g),r=m>=Math.abs(l-v),n&&(i.position.top=s._convertPositionTo("relative",{top:u,left:0}).top),a&&(i.position.top=s._convertPositionTo("relative",{top:d-s.helperProportions.height,left:0}).top),o&&(i.position.left=s._convertPositionTo("relative",{top:0,left:h}).left),r&&(i.position.left=s._convertPositionTo("relative",{top:0,left:l-s.helperProportions.width}).left)),!s.snapElements[c].snapping&&(n||a||o||r||p)&&s.options.snap.snap&&s.options.snap.snap.call(s.element,t,e.extend(s._uiHash(),{snapItem:s.snapElements[c].item})),s.snapElements[c].snapping=n||a||o||r||p)}}),e.ui.plugin.add("draggable","stack",{start:function(t,i,s){var n,a=s.options,o=e.makeArray(e(a.stack)).sort(function(t,i){return(parseInt(e(t).css("zIndex"),10)||0)-(parseInt(e(i).css("zIndex"),10)||0)});o.length&&(n=parseInt(e(o[0]).css("zIndex"),10)||0,e(o).each(function(t){e(this).css("zIndex",n+t)}),this.css("zIndex",n+o.length))}}),e.ui.plugin.add("draggable","zIndex",{start:function(t,i,s){var n=e(i.helper),a=s.options;n.css("zIndex")&&(a._zIndex=n.css("zIndex")),n.css("zIndex",a.zIndex)},stop:function(t,i,s){var n=s.options;n._zIndex&&e(i.helper).css("zIndex",n._zIndex)}}),e.ui.draggable,e.widget("ui.resizable",e.ui.mouse,{version:"1.11.4",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_num:function(e){return parseInt(e,10)||0},_isNumber:function(e){return!isNaN(parseInt(e,10))},_hasScroll:function(t,i){if("hidden"===e(t).css("overflow"))return!1;var s=i&&"left"===i?"scrollLeft":"scrollTop",n=!1;return t[s]>0?!0:(t[s]=1,n=t[s]>0,t[s]=0,n)},_create:function(){var t,i,s,n,a,o=this,r=this.options;if(this.element.addClass("ui-resizable"),e.extend(this,{_aspectRatio:!!r.aspectRatio,aspectRatio:r.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:r.helper||r.ghost||r.animate?r.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/^(canvas|textarea|input|select|button|img)$/i)&&(this.element.wrap(e("
      ").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.resizable("instance")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=r.handles||(e(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this._handles=e(),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),t=this.handles.split(","),this.handles={},i=0;t.length>i;i++)s=e.trim(t[i]),a="ui-resizable-"+s,n=e("
      "),n.css({zIndex:r.zIndex}),"se"===s&&n.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[s]=".ui-resizable-"+s,this.element.append(n);this._renderAxis=function(t){var i,s,n,a;t=t||this.element;for(i in this.handles)this.handles[i].constructor===String?this.handles[i]=this.element.children(this.handles[i]).first().show():(this.handles[i].jquery||this.handles[i].nodeType)&&(this.handles[i]=e(this.handles[i]),this._on(this.handles[i],{mousedown:o._mouseDown})),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/^(textarea|input|select|button)$/i)&&(s=e(this.handles[i],this.element),a=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join(""),t.css(n,a),this._proportionallyResize()),this._handles=this._handles.add(this.handles[i])},this._renderAxis(this.element),this._handles=this._handles.add(this.element.find(".ui-resizable-handle")),this._handles.disableSelection(),this._handles.mouseover(function(){o.resizing||(this.className&&(n=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),o.axis=n&&n[1]?n[1]:"se")}),r.autoHide&&(this._handles.hide(),e(this.element).addClass("ui-resizable-autohide").mouseenter(function(){r.disabled||(e(this).removeClass("ui-resizable-autohide"),o._handles.show())}).mouseleave(function(){r.disabled||o.resizing||(e(this).addClass("ui-resizable-autohide"),o._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var t,i=function(t){e(t).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(i(this.element),t=this.element,this.originalElement.css({position:t.css("position"),width:t.outerWidth(),height:t.outerHeight(),top:t.css("top"),left:t.css("left")}).insertAfter(t),t.remove()),this.originalElement.css("resize",this.originalResizeStyle),i(this.originalElement),this},_mouseCapture:function(t){var i,s,n=!1;for(i in this.handles)s=e(this.handles[i])[0],(s===t.target||e.contains(s,t.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(t){var i,s,n,a=this.options,o=this.element;return this.resizing=!0,this._renderProxy(),i=this._num(this.helper.css("left")),s=this._num(this.helper.css("top")),a.containment&&(i+=e(a.containment).scrollLeft()||0,s+=e(a.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:i,top:s},this.size=this._helper?{width:this.helper.width(),height:this.helper.height()}:{width:o.width(),height:o.height()},this.originalSize=this._helper?{width:o.outerWidth(),height:o.outerHeight()}:{width:o.width(),height:o.height()},this.sizeDiff={width:o.outerWidth()-o.width(),height:o.outerHeight()-o.height()},this.originalPosition={left:i,top:s},this.originalMousePosition={left:t.pageX,top:t.pageY},this.aspectRatio="number"==typeof a.aspectRatio?a.aspectRatio:this.originalSize.width/this.originalSize.height||1,n=e(".ui-resizable-"+this.axis).css("cursor"),e("body").css("cursor","auto"===n?this.axis+"-resize":n),o.addClass("ui-resizable-resizing"),this._propagate("start",t),!0},_mouseDrag:function(t){var i,s,n=this.originalMousePosition,a=this.axis,o=t.pageX-n.left||0,r=t.pageY-n.top||0,h=this._change[a];return this._updatePrevProperties(),h?(i=h.apply(this,[t,o,r]),this._updateVirtualBoundaries(t.shiftKey),(this._aspectRatio||t.shiftKey)&&(i=this._updateRatio(i,t)),i=this._respectSize(i,t),this._updateCache(i),this._propagate("resize",t),s=this._applyChanges(),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),e.isEmptyObject(s)||(this._updatePrevProperties(),this._trigger("resize",t,this.ui()),this._applyChanges()),!1):!1},_mouseStop:function(t){this.resizing=!1;var i,s,n,a,o,r,h,l=this.options,u=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&this._hasScroll(i[0],"left")?0:u.sizeDiff.height,a=s?0:u.sizeDiff.width,o={width:u.helper.width()-a,height:u.helper.height()-n},r=parseInt(u.element.css("left"),10)+(u.position.left-u.originalPosition.left)||null,h=parseInt(u.element.css("top"),10)+(u.position.top-u.originalPosition.top)||null,l.animate||this.element.css(e.extend(o,{top:h,left:r})),u.helper.height(u.size.height),u.helper.width(u.size.width),this._helper&&!l.animate&&this._proportionallyResize()),e("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",t),this._helper&&this.helper.remove(),!1},_updatePrevProperties:function(){this.prevPosition={top:this.position.top,left:this.position.left},this.prevSize={width:this.size.width,height:this.size.height}},_applyChanges:function(){var e={};return this.position.top!==this.prevPosition.top&&(e.top=this.position.top+"px"),this.position.left!==this.prevPosition.left&&(e.left=this.position.left+"px"),this.size.width!==this.prevSize.width&&(e.width=this.size.width+"px"),this.size.height!==this.prevSize.height&&(e.height=this.size.height+"px"),this.helper.css(e),e},_updateVirtualBoundaries:function(e){var t,i,s,n,a,o=this.options;a={minWidth:this._isNumber(o.minWidth)?o.minWidth:0,maxWidth:this._isNumber(o.maxWidth)?o.maxWidth:1/0,minHeight:this._isNumber(o.minHeight)?o.minHeight:0,maxHeight:this._isNumber(o.maxHeight)?o.maxHeight:1/0},(this._aspectRatio||e)&&(t=a.minHeight*this.aspectRatio,s=a.minWidth/this.aspectRatio,i=a.maxHeight*this.aspectRatio,n=a.maxWidth/this.aspectRatio,t>a.minWidth&&(a.minWidth=t),s>a.minHeight&&(a.minHeight=s),a.maxWidth>i&&(a.maxWidth=i),a.maxHeight>n&&(a.maxHeight=n)),this._vBoundaries=a},_updateCache:function(e){this.offset=this.helper.offset(),this._isNumber(e.left)&&(this.position.left=e.left),this._isNumber(e.top)&&(this.position.top=e.top),this._isNumber(e.height)&&(this.size.height=e.height),this._isNumber(e.width)&&(this.size.width=e.width)},_updateRatio:function(e){var t=this.position,i=this.size,s=this.axis;return this._isNumber(e.height)?e.width=e.height*this.aspectRatio:this._isNumber(e.width)&&(e.height=e.width/this.aspectRatio),"sw"===s&&(e.left=t.left+(i.width-e.width),e.top=null),"nw"===s&&(e.top=t.top+(i.height-e.height),e.left=t.left+(i.width-e.width)),e},_respectSize:function(e){var t=this._vBoundaries,i=this.axis,s=this._isNumber(e.width)&&t.maxWidth&&t.maxWidthe.width,o=this._isNumber(e.height)&&t.minHeight&&t.minHeight>e.height,r=this.originalPosition.left+this.originalSize.width,h=this.position.top+this.size.height,l=/sw|nw|w/.test(i),u=/nw|ne|n/.test(i);return a&&(e.width=t.minWidth),o&&(e.height=t.minHeight),s&&(e.width=t.maxWidth),n&&(e.height=t.maxHeight),a&&l&&(e.left=r-t.minWidth),s&&l&&(e.left=r-t.maxWidth),o&&u&&(e.top=h-t.minHeight),n&&u&&(e.top=h-t.maxHeight),e.width||e.height||e.left||!e.top?e.width||e.height||e.top||!e.left||(e.left=null):e.top=null,e},_getPaddingPlusBorderDimensions:function(e){for(var t=0,i=[],s=[e.css("borderTopWidth"),e.css("borderRightWidth"),e.css("borderBottomWidth"),e.css("borderLeftWidth")],n=[e.css("paddingTop"),e.css("paddingRight"),e.css("paddingBottom"),e.css("paddingLeft")];4>t;t++)i[t]=parseInt(s[t],10)||0,i[t]+=parseInt(n[t],10)||0;return{height:i[0]+i[2],width:i[1]+i[3]}},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var e,t=0,i=this.helper||this.element;this._proportionallyResizeElements.length>t;t++)e=this._proportionallyResizeElements[t],this.outerDimensions||(this.outerDimensions=this._getPaddingPlusBorderDimensions(e)),e.css({height:i.height()-this.outerDimensions.height||0,width:i.width()-this.outerDimensions.width||0})},_renderProxy:function(){var t=this.element,i=this.options;this.elementOffset=t.offset(),this._helper?(this.helper=this.helper||e("
      "),this.helper.addClass(this._helper).css({width:this.element.outerWidth()-1,height:this.element.outerHeight()-1,position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++i.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(e,t){return{width:this.originalSize.width+t}},w:function(e,t){var i=this.originalSize,s=this.originalPosition;return{left:s.left+t,width:i.width-t}},n:function(e,t,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(e,t,i){return{height:this.originalSize.height+i}},se:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},sw:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,i,s]))},ne:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},nw:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,i,s]))}},_propagate:function(t,i){e.ui.plugin.call(this,t,[i,this.ui()]),"resize"!==t&&this._trigger(t,i,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),e.ui.plugin.add("resizable","animate",{stop:function(t){var i=e(this).resizable("instance"),s=i.options,n=i._proportionallyResizeElements,a=n.length&&/textarea/i.test(n[0].nodeName),o=a&&i._hasScroll(n[0],"left")?0:i.sizeDiff.height,r=a?0:i.sizeDiff.width,h={width:i.size.width-r,height:i.size.height-o},l=parseInt(i.element.css("left"),10)+(i.position.left-i.originalPosition.left)||null,u=parseInt(i.element.css("top"),10)+(i.position.top-i.originalPosition.top)||null;i.element.animate(e.extend(h,u&&l?{top:u,left:l}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseInt(i.element.css("width"),10),height:parseInt(i.element.css("height"),10),top:parseInt(i.element.css("top"),10),left:parseInt(i.element.css("left"),10)};n&&n.length&&e(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate("resize",t)}})}}),e.ui.plugin.add("resizable","containment",{start:function(){var t,i,s,n,a,o,r,h=e(this).resizable("instance"),l=h.options,u=h.element,d=l.containment,c=d instanceof e?d.get(0):/parent/.test(d)?u.parent().get(0):d;c&&(h.containerElement=e(c),/document/.test(d)||d===document?(h.containerOffset={left:0,top:0},h.containerPosition={left:0,top:0},h.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight}):(t=e(c),i=[],e(["Top","Right","Left","Bottom"]).each(function(e,s){i[e]=h._num(t.css("padding"+s))}),h.containerOffset=t.offset(),h.containerPosition=t.position(),h.containerSize={height:t.innerHeight()-i[3],width:t.innerWidth()-i[1]},s=h.containerOffset,n=h.containerSize.height,a=h.containerSize.width,o=h._hasScroll(c,"left")?c.scrollWidth:a,r=h._hasScroll(c)?c.scrollHeight:n,h.parentData={element:c,left:s.left,top:s.top,width:o,height:r}))},resize:function(t){var i,s,n,a,o=e(this).resizable("instance"),r=o.options,h=o.containerOffset,l=o.position,u=o._aspectRatio||t.shiftKey,d={top:0,left:0},c=o.containerElement,p=!0;c[0]!==document&&/static/.test(c.css("position"))&&(d=h),l.left<(o._helper?h.left:0)&&(o.size.width=o.size.width+(o._helper?o.position.left-h.left:o.position.left-d.left),u&&(o.size.height=o.size.width/o.aspectRatio,p=!1),o.position.left=r.helper?h.left:0),l.top<(o._helper?h.top:0)&&(o.size.height=o.size.height+(o._helper?o.position.top-h.top:o.position.top),u&&(o.size.width=o.size.height*o.aspectRatio,p=!1),o.position.top=o._helper?h.top:0),n=o.containerElement.get(0)===o.element.parent().get(0),a=/relative|absolute/.test(o.containerElement.css("position")),n&&a?(o.offset.left=o.parentData.left+o.position.left,o.offset.top=o.parentData.top+o.position.top):(o.offset.left=o.element.offset().left,o.offset.top=o.element.offset().top),i=Math.abs(o.sizeDiff.width+(o._helper?o.offset.left-d.left:o.offset.left-h.left)),s=Math.abs(o.sizeDiff.height+(o._helper?o.offset.top-d.top:o.offset.top-h.top)),i+o.size.width>=o.parentData.width&&(o.size.width=o.parentData.width-i,u&&(o.size.height=o.size.width/o.aspectRatio,p=!1)),s+o.size.height>=o.parentData.height&&(o.size.height=o.parentData.height-s,u&&(o.size.width=o.size.height*o.aspectRatio,p=!1)),p||(o.position.left=o.prevPosition.left,o.position.top=o.prevPosition.top,o.size.width=o.prevSize.width,o.size.height=o.prevSize.height)},stop:function(){var t=e(this).resizable("instance"),i=t.options,s=t.containerOffset,n=t.containerPosition,a=t.containerElement,o=e(t.helper),r=o.offset(),h=o.outerWidth()-t.sizeDiff.width,l=o.outerHeight()-t.sizeDiff.height;t._helper&&!i.animate&&/relative/.test(a.css("position"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l}),t._helper&&!i.animate&&/static/.test(a.css("position"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l})}}),e.ui.plugin.add("resizable","alsoResize",{start:function(){var t=e(this).resizable("instance"),i=t.options;e(i.alsoResize).each(function(){var t=e(this);t.data("ui-resizable-alsoresize",{width:parseInt(t.width(),10),height:parseInt(t.height(),10),left:parseInt(t.css("left"),10),top:parseInt(t.css("top"),10)})})},resize:function(t,i){var s=e(this).resizable("instance"),n=s.options,a=s.originalSize,o=s.originalPosition,r={height:s.size.height-a.height||0,width:s.size.width-a.width||0,top:s.position.top-o.top||0,left:s.position.left-o.left||0};e(n.alsoResize).each(function(){var t=e(this),s=e(this).data("ui-resizable-alsoresize"),n={},a=t.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(a,function(e,t){var i=(s[t]||0)+(r[t]||0);i&&i>=0&&(n[t]=i||null)}),t.css(n)})},stop:function(){e(this).removeData("resizable-alsoresize")}}),e.ui.plugin.add("resizable","ghost",{start:function(){var t=e(this).resizable("instance"),i=t.options,s=t.size;t.ghost=t.originalElement.clone(),t.ghost.css({opacity:.25,display:"block",position:"relative",height:s.height,width:s.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass("string"==typeof i.ghost?i.ghost:""),t.ghost.appendTo(t.helper)},resize:function(){var t=e(this).resizable("instance");t.ghost&&t.ghost.css({position:"relative",height:t.size.height,width:t.size.width})},stop:function(){var t=e(this).resizable("instance");t.ghost&&t.helper&&t.helper.get(0).removeChild(t.ghost.get(0))}}),e.ui.plugin.add("resizable","grid",{resize:function(){var t,i=e(this).resizable("instance"),s=i.options,n=i.size,a=i.originalSize,o=i.originalPosition,r=i.axis,h="number"==typeof s.grid?[s.grid,s.grid]:s.grid,l=h[0]||1,u=h[1]||1,d=Math.round((n.width-a.width)/l)*l,c=Math.round((n.height-a.height)/u)*u,p=a.width+d,f=a.height+c,m=s.maxWidth&&p>s.maxWidth,g=s.maxHeight&&f>s.maxHeight,v=s.minWidth&&s.minWidth>p,y=s.minHeight&&s.minHeight>f;s.grid=h,v&&(p+=l),y&&(f+=u),m&&(p-=l),g&&(f-=u),/^(se|s|e)$/.test(r)?(i.size.width=p,i.size.height=f):/^(ne)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.top=o.top-c):/^(sw)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.left=o.left-d):((0>=f-u||0>=p-l)&&(t=i._getPaddingPlusBorderDimensions(this)),f-u>0?(i.size.height=f,i.position.top=o.top-c):(f=u-t.height,i.size.height=f,i.position.top=o.top+a.height-f),p-l>0?(i.size.width=p,i.position.left=o.left-d):(p=l-t.width,i.size.width=p,i.position.left=o.left+a.width-p))}}),e.ui.resizable,e.widget("ui.dialog",{version:"1.11.4",options:{appendTo:"body",autoOpen:!0,buttons:[],closeOnEscape:!0,closeText:"Close",dialogClass:"",draggable:!0,hide:null,height:"auto",maxHeight:null,maxWidth:null,minHeight:150,minWidth:150,modal:!1,position:{my:"center",at:"center",of:window,collision:"fit",using:function(t){var i=e(this).css(t).offset().top;0>i&&e(this).css("top",t.top-i)}},resizable:!0,show:null,title:null,width:300,beforeClose:null,close:null,drag:null,dragStart:null,dragStop:null,focus:null,open:null,resize:null,resizeStart:null,resizeStop:null},sizeRelatedOptions:{buttons:!0,height:!0,maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0,width:!0},resizableRelatedOptions:{maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0},_create:function(){this.originalCss={display:this.element[0].style.display,width:this.element[0].style.width,minHeight:this.element[0].style.minHeight,maxHeight:this.element[0].style.maxHeight,height:this.element[0].style.height},this.originalPosition={parent:this.element.parent(),index:this.element.parent().children().index(this.element)},this.originalTitle=this.element.attr("title"),this.options.title=this.options.title||this.originalTitle,this._createWrapper(),this.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(this.uiDialog),this._createTitlebar(),this._createButtonPane(),this.options.draggable&&e.fn.draggable&&this._makeDraggable(),this.options.resizable&&e.fn.resizable&&this._makeResizable(),this._isOpen=!1,this._trackFocus()},_init:function(){this.options.autoOpen&&this.open()},_appendTo:function(){var t=this.options.appendTo;return t&&(t.jquery||t.nodeType)?e(t):this.document.find(t||"body").eq(0)},_destroy:function(){var e,t=this.originalPosition;this._untrackInstance(),this._destroyOverlay(),this.element.removeUniqueId().removeClass("ui-dialog-content ui-widget-content").css(this.originalCss).detach(),this.uiDialog.stop(!0,!0).remove(),this.originalTitle&&this.element.attr("title",this.originalTitle),e=t.parent.children().eq(t.index),e.length&&e[0]!==this.element[0]?e.before(this.element):t.parent.append(this.element)},widget:function(){return this.uiDialog},disable:e.noop,enable:e.noop,close:function(t){var i,s=this;if(this._isOpen&&this._trigger("beforeClose",t)!==!1){if(this._isOpen=!1,this._focusedElement=null,this._destroyOverlay(),this._untrackInstance(),!this.opener.filter(":focusable").focus().length)try{i=this.document[0].activeElement,i&&"body"!==i.nodeName.toLowerCase()&&e(i).blur()}catch(n){}this._hide(this.uiDialog,this.options.hide,function(){s._trigger("close",t)})}},isOpen:function(){return this._isOpen},moveToTop:function(){this._moveToTop()},_moveToTop:function(t,i){var s=!1,n=this.uiDialog.siblings(".ui-front:visible").map(function(){return+e(this).css("z-index")}).get(),a=Math.max.apply(null,n);return a>=+this.uiDialog.css("z-index")&&(this.uiDialog.css("z-index",a+1),s=!0),s&&!i&&this._trigger("focus",t),s},open:function(){var t=this;return this._isOpen?(this._moveToTop()&&this._focusTabbable(),void 0):(this._isOpen=!0,this.opener=e(this.document[0].activeElement),this._size(),this._position(),this._createOverlay(),this._moveToTop(null,!0),this.overlay&&this.overlay.css("z-index",this.uiDialog.css("z-index")-1),this._show(this.uiDialog,this.options.show,function(){t._focusTabbable(),t._trigger("focus")}),this._makeFocusTarget(),this._trigger("open"),void 0)},_focusTabbable:function(){var e=this._focusedElement;e||(e=this.element.find("[autofocus]")),e.length||(e=this.element.find(":tabbable")),e.length||(e=this.uiDialogButtonPane.find(":tabbable")),e.length||(e=this.uiDialogTitlebarClose.filter(":tabbable")),e.length||(e=this.uiDialog),e.eq(0).focus()},_keepFocus:function(t){function i(){var t=this.document[0].activeElement,i=this.uiDialog[0]===t||e.contains(this.uiDialog[0],t);i||this._focusTabbable()}t.preventDefault(),i.call(this),this._delay(i)},_createWrapper:function(){this.uiDialog=e("
      ").addClass("ui-dialog ui-widget ui-widget-content ui-corner-all ui-front "+this.options.dialogClass).hide().attr({tabIndex:-1,role:"dialog"}).appendTo(this._appendTo()),this._on(this.uiDialog,{keydown:function(t){if(this.options.closeOnEscape&&!t.isDefaultPrevented()&&t.keyCode&&t.keyCode===e.ui.keyCode.ESCAPE)return t.preventDefault(),this.close(t),void 0; +if(t.keyCode===e.ui.keyCode.TAB&&!t.isDefaultPrevented()){var i=this.uiDialog.find(":tabbable"),s=i.filter(":first"),n=i.filter(":last");t.target!==n[0]&&t.target!==this.uiDialog[0]||t.shiftKey?t.target!==s[0]&&t.target!==this.uiDialog[0]||!t.shiftKey||(this._delay(function(){n.focus()}),t.preventDefault()):(this._delay(function(){s.focus()}),t.preventDefault())}},mousedown:function(e){this._moveToTop(e)&&this._focusTabbable()}}),this.element.find("[aria-describedby]").length||this.uiDialog.attr({"aria-describedby":this.element.uniqueId().attr("id")})},_createTitlebar:function(){var t;this.uiDialogTitlebar=e("
      ").addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(this.uiDialog),this._on(this.uiDialogTitlebar,{mousedown:function(t){e(t.target).closest(".ui-dialog-titlebar-close")||this.uiDialog.focus()}}),this.uiDialogTitlebarClose=e("").button({label:this.options.closeText,icons:{primary:"ui-icon-closethick"},text:!1}).addClass("ui-dialog-titlebar-close").appendTo(this.uiDialogTitlebar),this._on(this.uiDialogTitlebarClose,{click:function(e){e.preventDefault(),this.close(e)}}),t=e("").uniqueId().addClass("ui-dialog-title").prependTo(this.uiDialogTitlebar),this._title(t),this.uiDialog.attr({"aria-labelledby":t.attr("id")})},_title:function(e){this.options.title||e.html(" "),e.text(this.options.title)},_createButtonPane:function(){this.uiDialogButtonPane=e("
      ").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),this.uiButtonSet=e("
      ").addClass("ui-dialog-buttonset").appendTo(this.uiDialogButtonPane),this._createButtons()},_createButtons:function(){var t=this,i=this.options.buttons;return this.uiDialogButtonPane.remove(),this.uiButtonSet.empty(),e.isEmptyObject(i)||e.isArray(i)&&!i.length?(this.uiDialog.removeClass("ui-dialog-buttons"),void 0):(e.each(i,function(i,s){var n,a;s=e.isFunction(s)?{click:s,text:i}:s,s=e.extend({type:"button"},s),n=s.click,s.click=function(){n.apply(t.element[0],arguments)},a={icons:s.icons,text:s.showText},delete s.icons,delete s.showText,e("",s).button(a).appendTo(t.uiButtonSet)}),this.uiDialog.addClass("ui-dialog-buttons"),this.uiDialogButtonPane.appendTo(this.uiDialog),void 0)},_makeDraggable:function(){function t(e){return{position:e.position,offset:e.offset}}var i=this,s=this.options;this.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(s,n){e(this).addClass("ui-dialog-dragging"),i._blockFrames(),i._trigger("dragStart",s,t(n))},drag:function(e,s){i._trigger("drag",e,t(s))},stop:function(n,a){var o=a.offset.left-i.document.scrollLeft(),r=a.offset.top-i.document.scrollTop();s.position={my:"left top",at:"left"+(o>=0?"+":"")+o+" "+"top"+(r>=0?"+":"")+r,of:i.window},e(this).removeClass("ui-dialog-dragging"),i._unblockFrames(),i._trigger("dragStop",n,t(a))}})},_makeResizable:function(){function t(e){return{originalPosition:e.originalPosition,originalSize:e.originalSize,position:e.position,size:e.size}}var i=this,s=this.options,n=s.resizable,a=this.uiDialog.css("position"),o="string"==typeof n?n:"n,e,s,w,se,sw,ne,nw";this.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:this.element,maxWidth:s.maxWidth,maxHeight:s.maxHeight,minWidth:s.minWidth,minHeight:this._minHeight(),handles:o,start:function(s,n){e(this).addClass("ui-dialog-resizing"),i._blockFrames(),i._trigger("resizeStart",s,t(n))},resize:function(e,s){i._trigger("resize",e,t(s))},stop:function(n,a){var o=i.uiDialog.offset(),r=o.left-i.document.scrollLeft(),h=o.top-i.document.scrollTop();s.height=i.uiDialog.height(),s.width=i.uiDialog.width(),s.position={my:"left top",at:"left"+(r>=0?"+":"")+r+" "+"top"+(h>=0?"+":"")+h,of:i.window},e(this).removeClass("ui-dialog-resizing"),i._unblockFrames(),i._trigger("resizeStop",n,t(a))}}).css("position",a)},_trackFocus:function(){this._on(this.widget(),{focusin:function(t){this._makeFocusTarget(),this._focusedElement=e(t.target)}})},_makeFocusTarget:function(){this._untrackInstance(),this._trackingInstances().unshift(this)},_untrackInstance:function(){var t=this._trackingInstances(),i=e.inArray(this,t);-1!==i&&t.splice(i,1)},_trackingInstances:function(){var e=this.document.data("ui-dialog-instances");return e||(e=[],this.document.data("ui-dialog-instances",e)),e},_minHeight:function(){var e=this.options;return"auto"===e.height?e.minHeight:Math.min(e.minHeight,e.height)},_position:function(){var e=this.uiDialog.is(":visible");e||this.uiDialog.show(),this.uiDialog.position(this.options.position),e||this.uiDialog.hide()},_setOptions:function(t){var i=this,s=!1,n={};e.each(t,function(e,t){i._setOption(e,t),e in i.sizeRelatedOptions&&(s=!0),e in i.resizableRelatedOptions&&(n[e]=t)}),s&&(this._size(),this._position()),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option",n)},_setOption:function(e,t){var i,s,n=this.uiDialog;"dialogClass"===e&&n.removeClass(this.options.dialogClass).addClass(t),"disabled"!==e&&(this._super(e,t),"appendTo"===e&&this.uiDialog.appendTo(this._appendTo()),"buttons"===e&&this._createButtons(),"closeText"===e&&this.uiDialogTitlebarClose.button({label:""+t}),"draggable"===e&&(i=n.is(":data(ui-draggable)"),i&&!t&&n.draggable("destroy"),!i&&t&&this._makeDraggable()),"position"===e&&this._position(),"resizable"===e&&(s=n.is(":data(ui-resizable)"),s&&!t&&n.resizable("destroy"),s&&"string"==typeof t&&n.resizable("option","handles",t),s||t===!1||this._makeResizable()),"title"===e&&this._title(this.uiDialogTitlebar.find(".ui-dialog-title")))},_size:function(){var e,t,i,s=this.options;this.element.show().css({width:"auto",minHeight:0,maxHeight:"none",height:0}),s.minWidth>s.width&&(s.width=s.minWidth),e=this.uiDialog.css({height:"auto",width:s.width}).outerHeight(),t=Math.max(0,s.minHeight-e),i="number"==typeof s.maxHeight?Math.max(0,s.maxHeight-e):"none","auto"===s.height?this.element.css({minHeight:t,maxHeight:i,height:"auto"}):this.element.height(Math.max(0,s.height-e)),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())},_blockFrames:function(){this.iframeBlocks=this.document.find("iframe").map(function(){var t=e(this);return e("
      ").css({position:"absolute",width:t.outerWidth(),height:t.outerHeight()}).appendTo(t.parent()).offset(t.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_allowInteraction:function(t){return e(t.target).closest(".ui-dialog").length?!0:!!e(t.target).closest(".ui-datepicker").length},_createOverlay:function(){if(this.options.modal){var t=!0;this._delay(function(){t=!1}),this.document.data("ui-dialog-overlays")||this._on(this.document,{focusin:function(e){t||this._allowInteraction(e)||(e.preventDefault(),this._trackingInstances()[0]._focusTabbable())}}),this.overlay=e("
      ").addClass("ui-widget-overlay ui-front").appendTo(this._appendTo()),this._on(this.overlay,{mousedown:"_keepFocus"}),this.document.data("ui-dialog-overlays",(this.document.data("ui-dialog-overlays")||0)+1)}},_destroyOverlay:function(){if(this.options.modal&&this.overlay){var e=this.document.data("ui-dialog-overlays")-1;e?this.document.data("ui-dialog-overlays",e):this.document.unbind("focusin").removeData("ui-dialog-overlays"),this.overlay.remove(),this.overlay=null}}}),e.widget("ui.droppable",{version:"1.11.4",widgetEventPrefix:"drop",options:{accept:"*",activeClass:!1,addClasses:!0,greedy:!1,hoverClass:!1,scope:"default",tolerance:"intersect",activate:null,deactivate:null,drop:null,out:null,over:null},_create:function(){var t,i=this.options,s=i.accept;this.isover=!1,this.isout=!0,this.accept=e.isFunction(s)?s:function(e){return e.is(s)},this.proportions=function(){return arguments.length?(t=arguments[0],void 0):t?t:t={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight}},this._addToManager(i.scope),i.addClasses&&this.element.addClass("ui-droppable")},_addToManager:function(t){e.ui.ddmanager.droppables[t]=e.ui.ddmanager.droppables[t]||[],e.ui.ddmanager.droppables[t].push(this)},_splice:function(e){for(var t=0;e.length>t;t++)e[t]===this&&e.splice(t,1)},_destroy:function(){var t=e.ui.ddmanager.droppables[this.options.scope];this._splice(t),this.element.removeClass("ui-droppable ui-droppable-disabled")},_setOption:function(t,i){if("accept"===t)this.accept=e.isFunction(i)?i:function(e){return e.is(i)};else if("scope"===t){var s=e.ui.ddmanager.droppables[this.options.scope];this._splice(s),this._addToManager(i)}this._super(t,i)},_activate:function(t){var i=e.ui.ddmanager.current;this.options.activeClass&&this.element.addClass(this.options.activeClass),i&&this._trigger("activate",t,this.ui(i))},_deactivate:function(t){var i=e.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass),i&&this._trigger("deactivate",t,this.ui(i))},_over:function(t){var i=e.ui.ddmanager.current;i&&(i.currentItem||i.element)[0]!==this.element[0]&&this.accept.call(this.element[0],i.currentItem||i.element)&&(this.options.hoverClass&&this.element.addClass(this.options.hoverClass),this._trigger("over",t,this.ui(i)))},_out:function(t){var i=e.ui.ddmanager.current;i&&(i.currentItem||i.element)[0]!==this.element[0]&&this.accept.call(this.element[0],i.currentItem||i.element)&&(this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("out",t,this.ui(i)))},_drop:function(t,i){var s=i||e.ui.ddmanager.current,n=!1;return s&&(s.currentItem||s.element)[0]!==this.element[0]?(this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function(){var i=e(this).droppable("instance");return i.options.greedy&&!i.options.disabled&&i.options.scope===s.options.scope&&i.accept.call(i.element[0],s.currentItem||s.element)&&e.ui.intersect(s,e.extend(i,{offset:i.element.offset()}),i.options.tolerance,t)?(n=!0,!1):void 0}),n?!1:this.accept.call(this.element[0],s.currentItem||s.element)?(this.options.activeClass&&this.element.removeClass(this.options.activeClass),this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("drop",t,this.ui(s)),this.element):!1):!1},ui:function(e){return{draggable:e.currentItem||e.element,helper:e.helper,position:e.position,offset:e.positionAbs}}}),e.ui.intersect=function(){function e(e,t,i){return e>=t&&t+i>e}return function(t,i,s,n){if(!i.offset)return!1;var a=(t.positionAbs||t.position.absolute).left+t.margins.left,o=(t.positionAbs||t.position.absolute).top+t.margins.top,r=a+t.helperProportions.width,h=o+t.helperProportions.height,l=i.offset.left,u=i.offset.top,d=l+i.proportions().width,c=u+i.proportions().height;switch(s){case"fit":return a>=l&&d>=r&&o>=u&&c>=h;case"intersect":return a+t.helperProportions.width/2>l&&d>r-t.helperProportions.width/2&&o+t.helperProportions.height/2>u&&c>h-t.helperProportions.height/2;case"pointer":return e(n.pageY,u,i.proportions().height)&&e(n.pageX,l,i.proportions().width);case"touch":return(o>=u&&c>=o||h>=u&&c>=h||u>o&&h>c)&&(a>=l&&d>=a||r>=l&&d>=r||l>a&&r>d);default:return!1}}}(),e.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(t,i){var s,n,a=e.ui.ddmanager.droppables[t.options.scope]||[],o=i?i.type:null,r=(t.currentItem||t.element).find(":data(ui-droppable)").addBack();e:for(s=0;a.length>s;s++)if(!(a[s].options.disabled||t&&!a[s].accept.call(a[s].element[0],t.currentItem||t.element))){for(n=0;r.length>n;n++)if(r[n]===a[s].element[0]){a[s].proportions().height=0;continue e}a[s].visible="none"!==a[s].element.css("display"),a[s].visible&&("mousedown"===o&&a[s]._activate.call(a[s],i),a[s].offset=a[s].element.offset(),a[s].proportions({width:a[s].element[0].offsetWidth,height:a[s].element[0].offsetHeight}))}},drop:function(t,i){var s=!1;return e.each((e.ui.ddmanager.droppables[t.options.scope]||[]).slice(),function(){this.options&&(!this.options.disabled&&this.visible&&e.ui.intersect(t,this,this.options.tolerance,i)&&(s=this._drop.call(this,i)||s),!this.options.disabled&&this.visible&&this.accept.call(this.element[0],t.currentItem||t.element)&&(this.isout=!0,this.isover=!1,this._deactivate.call(this,i)))}),s},dragStart:function(t,i){t.element.parentsUntil("body").bind("scroll.droppable",function(){t.options.refreshPositions||e.ui.ddmanager.prepareOffsets(t,i)})},drag:function(t,i){t.options.refreshPositions&&e.ui.ddmanager.prepareOffsets(t,i),e.each(e.ui.ddmanager.droppables[t.options.scope]||[],function(){if(!this.options.disabled&&!this.greedyChild&&this.visible){var s,n,a,o=e.ui.intersect(t,this,this.options.tolerance,i),r=!o&&this.isover?"isout":o&&!this.isover?"isover":null;r&&(this.options.greedy&&(n=this.options.scope,a=this.element.parents(":data(ui-droppable)").filter(function(){return e(this).droppable("instance").options.scope===n}),a.length&&(s=e(a[0]).droppable("instance"),s.greedyChild="isover"===r)),s&&"isover"===r&&(s.isover=!1,s.isout=!0,s._out.call(s,i)),this[r]=!0,this["isout"===r?"isover":"isout"]=!1,this["isover"===r?"_over":"_out"].call(this,i),s&&"isout"===r&&(s.isout=!1,s.isover=!0,s._over.call(s,i)))}})},dragStop:function(t,i){t.element.parentsUntil("body").unbind("scroll.droppable"),t.options.refreshPositions||e.ui.ddmanager.prepareOffsets(t,i)}},e.ui.droppable;var y="ui-effects-",b=e;e.effects={effect:{}},function(e,t){function i(e,t,i){var s=d[t.type]||{};return null==e?i||!t.def?null:t.def:(e=s.floor?~~e:parseFloat(e),isNaN(e)?t.def:s.mod?(e+s.mod)%s.mod:0>e?0:e>s.max?s.max:e)}function s(i){var s=l(),n=s._rgba=[];return i=i.toLowerCase(),f(h,function(e,a){var o,r=a.re.exec(i),h=r&&a.parse(r),l=a.space||"rgba";return h?(o=s[l](h),s[u[l].cache]=o[u[l].cache],n=s._rgba=o._rgba,!1):t}),n.length?("0,0,0,0"===n.join()&&e.extend(n,a.transparent),s):a[i]}function n(e,t,i){return i=(i+1)%1,1>6*i?e+6*(t-e)*i:1>2*i?t:2>3*i?e+6*(t-e)*(2/3-i):e}var a,o="backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",r=/^([\-+])=\s*(\d+\.?\d*)/,h=[{re:/rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,parse:function(e){return[e[1],e[2],e[3],e[4]]}},{re:/rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,parse:function(e){return[2.55*e[1],2.55*e[2],2.55*e[3],e[4]]}},{re:/#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,parse:function(e){return[parseInt(e[1],16),parseInt(e[2],16),parseInt(e[3],16)]}},{re:/#([a-f0-9])([a-f0-9])([a-f0-9])/,parse:function(e){return[parseInt(e[1]+e[1],16),parseInt(e[2]+e[2],16),parseInt(e[3]+e[3],16)]}},{re:/hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,space:"hsla",parse:function(e){return[e[1],e[2]/100,e[3]/100,e[4]]}}],l=e.Color=function(t,i,s,n){return new e.Color.fn.parse(t,i,s,n)},u={rgba:{props:{red:{idx:0,type:"byte"},green:{idx:1,type:"byte"},blue:{idx:2,type:"byte"}}},hsla:{props:{hue:{idx:0,type:"degrees"},saturation:{idx:1,type:"percent"},lightness:{idx:2,type:"percent"}}}},d={"byte":{floor:!0,max:255},percent:{max:1},degrees:{mod:360,floor:!0}},c=l.support={},p=e("

      ")[0],f=e.each;p.style.cssText="background-color:rgba(1,1,1,.5)",c.rgba=p.style.backgroundColor.indexOf("rgba")>-1,f(u,function(e,t){t.cache="_"+e,t.props.alpha={idx:3,type:"percent",def:1}}),l.fn=e.extend(l.prototype,{parse:function(n,o,r,h){if(n===t)return this._rgba=[null,null,null,null],this;(n.jquery||n.nodeType)&&(n=e(n).css(o),o=t);var d=this,c=e.type(n),p=this._rgba=[];return o!==t&&(n=[n,o,r,h],c="array"),"string"===c?this.parse(s(n)||a._default):"array"===c?(f(u.rgba.props,function(e,t){p[t.idx]=i(n[t.idx],t)}),this):"object"===c?(n instanceof l?f(u,function(e,t){n[t.cache]&&(d[t.cache]=n[t.cache].slice())}):f(u,function(t,s){var a=s.cache;f(s.props,function(e,t){if(!d[a]&&s.to){if("alpha"===e||null==n[e])return;d[a]=s.to(d._rgba)}d[a][t.idx]=i(n[e],t,!0)}),d[a]&&0>e.inArray(null,d[a].slice(0,3))&&(d[a][3]=1,s.from&&(d._rgba=s.from(d[a])))}),this):t},is:function(e){var i=l(e),s=!0,n=this;return f(u,function(e,a){var o,r=i[a.cache];return r&&(o=n[a.cache]||a.to&&a.to(n._rgba)||[],f(a.props,function(e,i){return null!=r[i.idx]?s=r[i.idx]===o[i.idx]:t})),s}),s},_space:function(){var e=[],t=this;return f(u,function(i,s){t[s.cache]&&e.push(i)}),e.pop()},transition:function(e,t){var s=l(e),n=s._space(),a=u[n],o=0===this.alpha()?l("transparent"):this,r=o[a.cache]||a.to(o._rgba),h=r.slice();return s=s[a.cache],f(a.props,function(e,n){var a=n.idx,o=r[a],l=s[a],u=d[n.type]||{};null!==l&&(null===o?h[a]=l:(u.mod&&(l-o>u.mod/2?o+=u.mod:o-l>u.mod/2&&(o-=u.mod)),h[a]=i((l-o)*t+o,n)))}),this[n](h)},blend:function(t){if(1===this._rgba[3])return this;var i=this._rgba.slice(),s=i.pop(),n=l(t)._rgba;return l(e.map(i,function(e,t){return(1-s)*n[t]+s*e}))},toRgbaString:function(){var t="rgba(",i=e.map(this._rgba,function(e,t){return null==e?t>2?1:0:e});return 1===i[3]&&(i.pop(),t="rgb("),t+i.join()+")"},toHslaString:function(){var t="hsla(",i=e.map(this.hsla(),function(e,t){return null==e&&(e=t>2?1:0),t&&3>t&&(e=Math.round(100*e)+"%"),e});return 1===i[3]&&(i.pop(),t="hsl("),t+i.join()+")"},toHexString:function(t){var i=this._rgba.slice(),s=i.pop();return t&&i.push(~~(255*s)),"#"+e.map(i,function(e){return e=(e||0).toString(16),1===e.length?"0"+e:e}).join("")},toString:function(){return 0===this._rgba[3]?"transparent":this.toRgbaString()}}),l.fn.parse.prototype=l.fn,u.hsla.to=function(e){if(null==e[0]||null==e[1]||null==e[2])return[null,null,null,e[3]];var t,i,s=e[0]/255,n=e[1]/255,a=e[2]/255,o=e[3],r=Math.max(s,n,a),h=Math.min(s,n,a),l=r-h,u=r+h,d=.5*u;return t=h===r?0:s===r?60*(n-a)/l+360:n===r?60*(a-s)/l+120:60*(s-n)/l+240,i=0===l?0:.5>=d?l/u:l/(2-u),[Math.round(t)%360,i,d,null==o?1:o]},u.hsla.from=function(e){if(null==e[0]||null==e[1]||null==e[2])return[null,null,null,e[3]];var t=e[0]/360,i=e[1],s=e[2],a=e[3],o=.5>=s?s*(1+i):s+i-s*i,r=2*s-o;return[Math.round(255*n(r,o,t+1/3)),Math.round(255*n(r,o,t)),Math.round(255*n(r,o,t-1/3)),a]},f(u,function(s,n){var a=n.props,o=n.cache,h=n.to,u=n.from;l.fn[s]=function(s){if(h&&!this[o]&&(this[o]=h(this._rgba)),s===t)return this[o].slice();var n,r=e.type(s),d="array"===r||"object"===r?s:arguments,c=this[o].slice();return f(a,function(e,t){var s=d["object"===r?e:t.idx];null==s&&(s=c[t.idx]),c[t.idx]=i(s,t)}),u?(n=l(u(c)),n[o]=c,n):l(c)},f(a,function(t,i){l.fn[t]||(l.fn[t]=function(n){var a,o=e.type(n),h="alpha"===t?this._hsla?"hsla":"rgba":s,l=this[h](),u=l[i.idx];return"undefined"===o?u:("function"===o&&(n=n.call(this,u),o=e.type(n)),null==n&&i.empty?this:("string"===o&&(a=r.exec(n),a&&(n=u+parseFloat(a[2])*("+"===a[1]?1:-1))),l[i.idx]=n,this[h](l)))})})}),l.hook=function(t){var i=t.split(" ");f(i,function(t,i){e.cssHooks[i]={set:function(t,n){var a,o,r="";if("transparent"!==n&&("string"!==e.type(n)||(a=s(n)))){if(n=l(a||n),!c.rgba&&1!==n._rgba[3]){for(o="backgroundColor"===i?t.parentNode:t;(""===r||"transparent"===r)&&o&&o.style;)try{r=e.css(o,"backgroundColor"),o=o.parentNode}catch(h){}n=n.blend(r&&"transparent"!==r?r:"_default")}n=n.toRgbaString()}try{t.style[i]=n}catch(h){}}},e.fx.step[i]=function(t){t.colorInit||(t.start=l(t.elem,i),t.end=l(t.end),t.colorInit=!0),e.cssHooks[i].set(t.elem,t.start.transition(t.end,t.pos))}})},l.hook(o),e.cssHooks.borderColor={expand:function(e){var t={};return f(["Top","Right","Bottom","Left"],function(i,s){t["border"+s+"Color"]=e}),t}},a=e.Color.names={aqua:"#00ffff",black:"#000000",blue:"#0000ff",fuchsia:"#ff00ff",gray:"#808080",green:"#008000",lime:"#00ff00",maroon:"#800000",navy:"#000080",olive:"#808000",purple:"#800080",red:"#ff0000",silver:"#c0c0c0",teal:"#008080",white:"#ffffff",yellow:"#ffff00",transparent:[null,null,null,0],_default:"#ffffff"}}(b),function(){function t(t){var i,s,n=t.ownerDocument.defaultView?t.ownerDocument.defaultView.getComputedStyle(t,null):t.currentStyle,a={};if(n&&n.length&&n[0]&&n[n[0]])for(s=n.length;s--;)i=n[s],"string"==typeof n[i]&&(a[e.camelCase(i)]=n[i]);else for(i in n)"string"==typeof n[i]&&(a[i]=n[i]);return a}function i(t,i){var s,a,o={};for(s in i)a=i[s],t[s]!==a&&(n[s]||(e.fx.step[s]||!isNaN(parseFloat(a)))&&(o[s]=a));return o}var s=["add","remove","toggle"],n={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};e.each(["borderLeftStyle","borderRightStyle","borderBottomStyle","borderTopStyle"],function(t,i){e.fx.step[i]=function(e){("none"!==e.end&&!e.setAttr||1===e.pos&&!e.setAttr)&&(b.style(e.elem,i,e.end),e.setAttr=!0)}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e.effects.animateClass=function(n,a,o,r){var h=e.speed(a,o,r);return this.queue(function(){var a,o=e(this),r=o.attr("class")||"",l=h.children?o.find("*").addBack():o;l=l.map(function(){var i=e(this);return{el:i,start:t(this)}}),a=function(){e.each(s,function(e,t){n[t]&&o[t+"Class"](n[t])})},a(),l=l.map(function(){return this.end=t(this.el[0]),this.diff=i(this.start,this.end),this}),o.attr("class",r),l=l.map(function(){var t=this,i=e.Deferred(),s=e.extend({},h,{queue:!1,complete:function(){i.resolve(t)}});return this.el.animate(this.diff,s),i.promise()}),e.when.apply(e,l.get()).done(function(){a(),e.each(arguments,function(){var t=this.el;e.each(this.diff,function(e){t.css(e,"")})}),h.complete.call(o[0])})})},e.fn.extend({addClass:function(t){return function(i,s,n,a){return s?e.effects.animateClass.call(this,{add:i},s,n,a):t.apply(this,arguments)}}(e.fn.addClass),removeClass:function(t){return function(i,s,n,a){return arguments.length>1?e.effects.animateClass.call(this,{remove:i},s,n,a):t.apply(this,arguments)}}(e.fn.removeClass),toggleClass:function(t){return function(i,s,n,a,o){return"boolean"==typeof s||void 0===s?n?e.effects.animateClass.call(this,s?{add:i}:{remove:i},n,a,o):t.apply(this,arguments):e.effects.animateClass.call(this,{toggle:i},s,n,a)}}(e.fn.toggleClass),switchClass:function(t,i,s,n,a){return e.effects.animateClass.call(this,{add:i,remove:t},s,n,a)}})}(),function(){function t(t,i,s,n){return e.isPlainObject(t)&&(i=t,t=t.effect),t={effect:t},null==i&&(i={}),e.isFunction(i)&&(n=i,s=null,i={}),("number"==typeof i||e.fx.speeds[i])&&(n=s,s=i,i={}),e.isFunction(s)&&(n=s,s=null),i&&e.extend(t,i),s=s||i.duration,t.duration=e.fx.off?0:"number"==typeof s?s:s in e.fx.speeds?e.fx.speeds[s]:e.fx.speeds._default,t.complete=n||i.complete,t}function i(t){return!t||"number"==typeof t||e.fx.speeds[t]?!0:"string"!=typeof t||e.effects.effect[t]?e.isFunction(t)?!0:"object"!=typeof t||t.effect?!1:!0:!0}e.extend(e.effects,{version:"1.11.4",save:function(e,t){for(var i=0;t.length>i;i++)null!==t[i]&&e.data(y+t[i],e[0].style[t[i]])},restore:function(e,t){var i,s;for(s=0;t.length>s;s++)null!==t[s]&&(i=e.data(y+t[s]),void 0===i&&(i=""),e.css(t[s],i))},setMode:function(e,t){return"toggle"===t&&(t=e.is(":hidden")?"show":"hide"),t},getBaseline:function(e,t){var i,s;switch(e[0]){case"top":i=0;break;case"middle":i=.5;break;case"bottom":i=1;break;default:i=e[0]/t.height}switch(e[1]){case"left":s=0;break;case"center":s=.5;break;case"right":s=1;break;default:s=e[1]/t.width}return{x:s,y:i}},createWrapper:function(t){if(t.parent().is(".ui-effects-wrapper"))return t.parent();var i={width:t.outerWidth(!0),height:t.outerHeight(!0),"float":t.css("float")},s=e("

      ").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),n={width:t.width(),height:t.height()},a=document.activeElement;try{a.id}catch(o){a=document.body}return t.wrap(s),(t[0]===a||e.contains(t[0],a))&&e(a).focus(),s=t.parent(),"static"===t.css("position")?(s.css({position:"relative"}),t.css({position:"relative"})):(e.extend(i,{position:t.css("position"),zIndex:t.css("z-index")}),e.each(["top","left","bottom","right"],function(e,s){i[s]=t.css(s),isNaN(parseInt(i[s],10))&&(i[s]="auto")}),t.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),t.css(n),s.css(i).show()},removeWrapper:function(t){var i=document.activeElement;return t.parent().is(".ui-effects-wrapper")&&(t.parent().replaceWith(t),(t[0]===i||e.contains(t[0],i))&&e(i).focus()),t},setTransition:function(t,i,s,n){return n=n||{},e.each(i,function(e,i){var a=t.cssUnit(i);a[0]>0&&(n[i]=a[0]*s+a[1])}),n}}),e.fn.extend({effect:function(){function i(t){function i(){e.isFunction(a)&&a.call(n[0]),e.isFunction(t)&&t()}var n=e(this),a=s.complete,r=s.mode;(n.is(":hidden")?"hide"===r:"show"===r)?(n[r](),i()):o.call(n[0],s,i)}var s=t.apply(this,arguments),n=s.mode,a=s.queue,o=e.effects.effect[s.effect];return e.fx.off||!o?n?this[n](s.duration,s.complete):this.each(function(){s.complete&&s.complete.call(this)}):a===!1?this.each(i):this.queue(a||"fx",i)},show:function(e){return function(s){if(i(s))return e.apply(this,arguments);var n=t.apply(this,arguments);return n.mode="show",this.effect.call(this,n)}}(e.fn.show),hide:function(e){return function(s){if(i(s))return e.apply(this,arguments);var n=t.apply(this,arguments);return n.mode="hide",this.effect.call(this,n)}}(e.fn.hide),toggle:function(e){return function(s){if(i(s)||"boolean"==typeof s)return e.apply(this,arguments);var n=t.apply(this,arguments);return n.mode="toggle",this.effect.call(this,n)}}(e.fn.toggle),cssUnit:function(t){var i=this.css(t),s=[];return e.each(["em","px","%","pt"],function(e,t){i.indexOf(t)>0&&(s=[parseFloat(i),t])}),s}})}(),function(){var t={};e.each(["Quad","Cubic","Quart","Quint","Expo"],function(e,i){t[i]=function(t){return Math.pow(t,e+2)}}),e.extend(t,{Sine:function(e){return 1-Math.cos(e*Math.PI/2)},Circ:function(e){return 1-Math.sqrt(1-e*e)},Elastic:function(e){return 0===e||1===e?e:-Math.pow(2,8*(e-1))*Math.sin((80*(e-1)-7.5)*Math.PI/15)},Back:function(e){return e*e*(3*e-2)},Bounce:function(e){for(var t,i=4;((t=Math.pow(2,--i))-1)/11>e;);return 1/Math.pow(4,3-i)-7.5625*Math.pow((3*t-2)/22-e,2)}}),e.each(t,function(t,i){e.easing["easeIn"+t]=i,e.easing["easeOut"+t]=function(e){return 1-i(1-e)},e.easing["easeInOut"+t]=function(e){return.5>e?i(2*e)/2:1-i(-2*e+2)/2}})}(),e.effects,e.effects.effect.blind=function(t,i){var s,n,a,o=e(this),r=/up|down|vertical/,h=/up|left|vertical|horizontal/,l=["position","top","bottom","left","right","height","width"],u=e.effects.setMode(o,t.mode||"hide"),d=t.direction||"up",c=r.test(d),p=c?"height":"width",f=c?"top":"left",m=h.test(d),g={},v="show"===u;o.parent().is(".ui-effects-wrapper")?e.effects.save(o.parent(),l):e.effects.save(o,l),o.show(),s=e.effects.createWrapper(o).css({overflow:"hidden"}),n=s[p](),a=parseFloat(s.css(f))||0,g[p]=v?n:0,m||(o.css(c?"bottom":"right",0).css(c?"top":"left","auto").css({position:"absolute"}),g[f]=v?a:n+a),v&&(s.css(p,0),m||s.css(f,a+n)),s.animate(g,{duration:t.duration,easing:t.easing,queue:!1,complete:function(){"hide"===u&&o.hide(),e.effects.restore(o,l),e.effects.removeWrapper(o),i()}})},e.effects.effect.bounce=function(t,i){var s,n,a,o=e(this),r=["position","top","bottom","left","right","height","width"],h=e.effects.setMode(o,t.mode||"effect"),l="hide"===h,u="show"===h,d=t.direction||"up",c=t.distance,p=t.times||5,f=2*p+(u||l?1:0),m=t.duration/f,g=t.easing,v="up"===d||"down"===d?"top":"left",y="up"===d||"left"===d,b=o.queue(),_=b.length;for((u||l)&&r.push("opacity"),e.effects.save(o,r),o.show(),e.effects.createWrapper(o),c||(c=o["top"===v?"outerHeight":"outerWidth"]()/3),u&&(a={opacity:1},a[v]=0,o.css("opacity",0).css(v,y?2*-c:2*c).animate(a,m,g)),l&&(c/=Math.pow(2,p-1)),a={},a[v]=0,s=0;p>s;s++)n={},n[v]=(y?"-=":"+=")+c,o.animate(n,m,g).animate(a,m,g),c=l?2*c:c/2;l&&(n={opacity:0},n[v]=(y?"-=":"+=")+c,o.animate(n,m,g)),o.queue(function(){l&&o.hide(),e.effects.restore(o,r),e.effects.removeWrapper(o),i()}),_>1&&b.splice.apply(b,[1,0].concat(b.splice(_,f+1))),o.dequeue()},e.effects.effect.clip=function(t,i){var s,n,a,o=e(this),r=["position","top","bottom","left","right","height","width"],h=e.effects.setMode(o,t.mode||"hide"),l="show"===h,u=t.direction||"vertical",d="vertical"===u,c=d?"height":"width",p=d?"top":"left",f={};e.effects.save(o,r),o.show(),s=e.effects.createWrapper(o).css({overflow:"hidden"}),n="IMG"===o[0].tagName?s:o,a=n[c](),l&&(n.css(c,0),n.css(p,a/2)),f[c]=l?a:0,f[p]=l?0:a/2,n.animate(f,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){l||o.hide(),e.effects.restore(o,r),e.effects.removeWrapper(o),i()}})},e.effects.effect.drop=function(t,i){var s,n=e(this),a=["position","top","bottom","left","right","opacity","height","width"],o=e.effects.setMode(n,t.mode||"hide"),r="show"===o,h=t.direction||"left",l="up"===h||"down"===h?"top":"left",u="up"===h||"left"===h?"pos":"neg",d={opacity:r?1:0};e.effects.save(n,a),n.show(),e.effects.createWrapper(n),s=t.distance||n["top"===l?"outerHeight":"outerWidth"](!0)/2,r&&n.css("opacity",0).css(l,"pos"===u?-s:s),d[l]=(r?"pos"===u?"+=":"-=":"pos"===u?"-=":"+=")+s,n.animate(d,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){"hide"===o&&n.hide(),e.effects.restore(n,a),e.effects.removeWrapper(n),i()}})},e.effects.effect.explode=function(t,i){function s(){b.push(this),b.length===d*c&&n()}function n(){p.css({visibility:"visible"}),e(b).remove(),m||p.hide(),i()}var a,o,r,h,l,u,d=t.pieces?Math.round(Math.sqrt(t.pieces)):3,c=d,p=e(this),f=e.effects.setMode(p,t.mode||"hide"),m="show"===f,g=p.show().css("visibility","hidden").offset(),v=Math.ceil(p.outerWidth()/c),y=Math.ceil(p.outerHeight()/d),b=[];for(a=0;d>a;a++)for(h=g.top+a*y,u=a-(d-1)/2,o=0;c>o;o++)r=g.left+o*v,l=o-(c-1)/2,p.clone().appendTo("body").wrap("
      ").css({position:"absolute",visibility:"visible",left:-o*v,top:-a*y}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:v,height:y,left:r+(m?l*v:0),top:h+(m?u*y:0),opacity:m?0:1}).animate({left:r+(m?0:l*v),top:h+(m?0:u*y),opacity:m?1:0},t.duration||500,t.easing,s)},e.effects.effect.fade=function(t,i){var s=e(this),n=e.effects.setMode(s,t.mode||"toggle");s.animate({opacity:n},{queue:!1,duration:t.duration,easing:t.easing,complete:i})},e.effects.effect.fold=function(t,i){var s,n,a=e(this),o=["position","top","bottom","left","right","height","width"],r=e.effects.setMode(a,t.mode||"hide"),h="show"===r,l="hide"===r,u=t.size||15,d=/([0-9]+)%/.exec(u),c=!!t.horizFirst,p=h!==c,f=p?["width","height"]:["height","width"],m=t.duration/2,g={},v={};e.effects.save(a,o),a.show(),s=e.effects.createWrapper(a).css({overflow:"hidden"}),n=p?[s.width(),s.height()]:[s.height(),s.width()],d&&(u=parseInt(d[1],10)/100*n[l?0:1]),h&&s.css(c?{height:0,width:u}:{height:u,width:0}),g[f[0]]=h?n[0]:u,v[f[1]]=h?n[1]:0,s.animate(g,m,t.easing).animate(v,m,t.easing,function(){l&&a.hide(),e.effects.restore(a,o),e.effects.removeWrapper(a),i()})},e.effects.effect.highlight=function(t,i){var s=e(this),n=["backgroundImage","backgroundColor","opacity"],a=e.effects.setMode(s,t.mode||"show"),o={backgroundColor:s.css("backgroundColor")};"hide"===a&&(o.opacity=0),e.effects.save(s,n),s.show().css({backgroundImage:"none",backgroundColor:t.color||"#ffff99"}).animate(o,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){"hide"===a&&s.hide(),e.effects.restore(s,n),i()}})},e.effects.effect.size=function(t,i){var s,n,a,o=e(this),r=["position","top","bottom","left","right","width","height","overflow","opacity"],h=["position","top","bottom","left","right","overflow","opacity"],l=["width","height","overflow"],u=["fontSize"],d=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],c=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],p=e.effects.setMode(o,t.mode||"effect"),f=t.restore||"effect"!==p,m=t.scale||"both",g=t.origin||["middle","center"],v=o.css("position"),y=f?r:h,b={height:0,width:0,outerHeight:0,outerWidth:0};"show"===p&&o.show(),s={height:o.height(),width:o.width(),outerHeight:o.outerHeight(),outerWidth:o.outerWidth()},"toggle"===t.mode&&"show"===p?(o.from=t.to||b,o.to=t.from||s):(o.from=t.from||("show"===p?b:s),o.to=t.to||("hide"===p?b:s)),a={from:{y:o.from.height/s.height,x:o.from.width/s.width},to:{y:o.to.height/s.height,x:o.to.width/s.width}},("box"===m||"both"===m)&&(a.from.y!==a.to.y&&(y=y.concat(d),o.from=e.effects.setTransition(o,d,a.from.y,o.from),o.to=e.effects.setTransition(o,d,a.to.y,o.to)),a.from.x!==a.to.x&&(y=y.concat(c),o.from=e.effects.setTransition(o,c,a.from.x,o.from),o.to=e.effects.setTransition(o,c,a.to.x,o.to))),("content"===m||"both"===m)&&a.from.y!==a.to.y&&(y=y.concat(u).concat(l),o.from=e.effects.setTransition(o,u,a.from.y,o.from),o.to=e.effects.setTransition(o,u,a.to.y,o.to)),e.effects.save(o,y),o.show(),e.effects.createWrapper(o),o.css("overflow","hidden").css(o.from),g&&(n=e.effects.getBaseline(g,s),o.from.top=(s.outerHeight-o.outerHeight())*n.y,o.from.left=(s.outerWidth-o.outerWidth())*n.x,o.to.top=(s.outerHeight-o.to.outerHeight)*n.y,o.to.left=(s.outerWidth-o.to.outerWidth)*n.x),o.css(o.from),("content"===m||"both"===m)&&(d=d.concat(["marginTop","marginBottom"]).concat(u),c=c.concat(["marginLeft","marginRight"]),l=r.concat(d).concat(c),o.find("*[width]").each(function(){var i=e(this),s={height:i.height(),width:i.width(),outerHeight:i.outerHeight(),outerWidth:i.outerWidth()}; +f&&e.effects.save(i,l),i.from={height:s.height*a.from.y,width:s.width*a.from.x,outerHeight:s.outerHeight*a.from.y,outerWidth:s.outerWidth*a.from.x},i.to={height:s.height*a.to.y,width:s.width*a.to.x,outerHeight:s.height*a.to.y,outerWidth:s.width*a.to.x},a.from.y!==a.to.y&&(i.from=e.effects.setTransition(i,d,a.from.y,i.from),i.to=e.effects.setTransition(i,d,a.to.y,i.to)),a.from.x!==a.to.x&&(i.from=e.effects.setTransition(i,c,a.from.x,i.from),i.to=e.effects.setTransition(i,c,a.to.x,i.to)),i.css(i.from),i.animate(i.to,t.duration,t.easing,function(){f&&e.effects.restore(i,l)})})),o.animate(o.to,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){0===o.to.opacity&&o.css("opacity",o.from.opacity),"hide"===p&&o.hide(),e.effects.restore(o,y),f||("static"===v?o.css({position:"relative",top:o.to.top,left:o.to.left}):e.each(["top","left"],function(e,t){o.css(t,function(t,i){var s=parseInt(i,10),n=e?o.to.left:o.to.top;return"auto"===i?n+"px":s+n+"px"})})),e.effects.removeWrapper(o),i()}})},e.effects.effect.scale=function(t,i){var s=e(this),n=e.extend(!0,{},t),a=e.effects.setMode(s,t.mode||"effect"),o=parseInt(t.percent,10)||(0===parseInt(t.percent,10)?0:"hide"===a?0:100),r=t.direction||"both",h=t.origin,l={height:s.height(),width:s.width(),outerHeight:s.outerHeight(),outerWidth:s.outerWidth()},u={y:"horizontal"!==r?o/100:1,x:"vertical"!==r?o/100:1};n.effect="size",n.queue=!1,n.complete=i,"effect"!==a&&(n.origin=h||["middle","center"],n.restore=!0),n.from=t.from||("show"===a?{height:0,width:0,outerHeight:0,outerWidth:0}:l),n.to={height:l.height*u.y,width:l.width*u.x,outerHeight:l.outerHeight*u.y,outerWidth:l.outerWidth*u.x},n.fade&&("show"===a&&(n.from.opacity=0,n.to.opacity=1),"hide"===a&&(n.from.opacity=1,n.to.opacity=0)),s.effect(n)},e.effects.effect.puff=function(t,i){var s=e(this),n=e.effects.setMode(s,t.mode||"hide"),a="hide"===n,o=parseInt(t.percent,10)||150,r=o/100,h={height:s.height(),width:s.width(),outerHeight:s.outerHeight(),outerWidth:s.outerWidth()};e.extend(t,{effect:"scale",queue:!1,fade:!0,mode:n,complete:i,percent:a?o:100,from:a?h:{height:h.height*r,width:h.width*r,outerHeight:h.outerHeight*r,outerWidth:h.outerWidth*r}}),s.effect(t)},e.effects.effect.pulsate=function(t,i){var s,n=e(this),a=e.effects.setMode(n,t.mode||"show"),o="show"===a,r="hide"===a,h=o||"hide"===a,l=2*(t.times||5)+(h?1:0),u=t.duration/l,d=0,c=n.queue(),p=c.length;for((o||!n.is(":visible"))&&(n.css("opacity",0).show(),d=1),s=1;l>s;s++)n.animate({opacity:d},u,t.easing),d=1-d;n.animate({opacity:d},u,t.easing),n.queue(function(){r&&n.hide(),i()}),p>1&&c.splice.apply(c,[1,0].concat(c.splice(p,l+1))),n.dequeue()},e.effects.effect.shake=function(t,i){var s,n=e(this),a=["position","top","bottom","left","right","height","width"],o=e.effects.setMode(n,t.mode||"effect"),r=t.direction||"left",h=t.distance||20,l=t.times||3,u=2*l+1,d=Math.round(t.duration/u),c="up"===r||"down"===r?"top":"left",p="up"===r||"left"===r,f={},m={},g={},v=n.queue(),y=v.length;for(e.effects.save(n,a),n.show(),e.effects.createWrapper(n),f[c]=(p?"-=":"+=")+h,m[c]=(p?"+=":"-=")+2*h,g[c]=(p?"-=":"+=")+2*h,n.animate(f,d,t.easing),s=1;l>s;s++)n.animate(m,d,t.easing).animate(g,d,t.easing);n.animate(m,d,t.easing).animate(f,d/2,t.easing).queue(function(){"hide"===o&&n.hide(),e.effects.restore(n,a),e.effects.removeWrapper(n),i()}),y>1&&v.splice.apply(v,[1,0].concat(v.splice(y,u+1))),n.dequeue()},e.effects.effect.slide=function(t,i){var s,n=e(this),a=["position","top","bottom","left","right","width","height"],o=e.effects.setMode(n,t.mode||"show"),r="show"===o,h=t.direction||"left",l="up"===h||"down"===h?"top":"left",u="up"===h||"left"===h,d={};e.effects.save(n,a),n.show(),s=t.distance||n["top"===l?"outerHeight":"outerWidth"](!0),e.effects.createWrapper(n).css({overflow:"hidden"}),r&&n.css(l,u?isNaN(s)?"-"+s:-s:s),d[l]=(r?u?"+=":"-=":u?"-=":"+=")+s,n.animate(d,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){"hide"===o&&n.hide(),e.effects.restore(n,a),e.effects.removeWrapper(n),i()}})},e.effects.effect.transfer=function(t,i){var s=e(this),n=e(t.to),a="fixed"===n.css("position"),o=e("body"),r=a?o.scrollTop():0,h=a?o.scrollLeft():0,l=n.offset(),u={top:l.top-r,left:l.left-h,height:n.innerHeight(),width:n.innerWidth()},d=s.offset(),c=e("
      ").appendTo(document.body).addClass(t.className).css({top:d.top-r,left:d.left-h,height:s.innerHeight(),width:s.innerWidth(),position:a?"fixed":"absolute"}).animate(u,t.duration,t.easing,function(){c.remove(),i()})},e.widget("ui.progressbar",{version:"1.11.4",options:{max:100,value:0,change:null,complete:null},min:0,_create:function(){this.oldValue=this.options.value=this._constrainedValue(),this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min}),this.valueDiv=e("
      ").appendTo(this.element),this._refreshValue()},_destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.valueDiv.remove()},value:function(e){return void 0===e?this.options.value:(this.options.value=this._constrainedValue(e),this._refreshValue(),void 0)},_constrainedValue:function(e){return void 0===e&&(e=this.options.value),this.indeterminate=e===!1,"number"!=typeof e&&(e=0),this.indeterminate?!1:Math.min(this.options.max,Math.max(this.min,e))},_setOptions:function(e){var t=e.value;delete e.value,this._super(e),this.options.value=this._constrainedValue(t),this._refreshValue()},_setOption:function(e,t){"max"===e&&(t=Math.max(this.min,t)),"disabled"===e&&this.element.toggleClass("ui-state-disabled",!!t).attr("aria-disabled",t),this._super(e,t)},_percentage:function(){return this.indeterminate?100:100*(this.options.value-this.min)/(this.options.max-this.min)},_refreshValue:function(){var t=this.options.value,i=this._percentage();this.valueDiv.toggle(this.indeterminate||t>this.min).toggleClass("ui-corner-right",t===this.options.max).width(i.toFixed(0)+"%"),this.element.toggleClass("ui-progressbar-indeterminate",this.indeterminate),this.indeterminate?(this.element.removeAttr("aria-valuenow"),this.overlayDiv||(this.overlayDiv=e("
      ").appendTo(this.valueDiv))):(this.element.attr({"aria-valuemax":this.options.max,"aria-valuenow":t}),this.overlayDiv&&(this.overlayDiv.remove(),this.overlayDiv=null)),this.oldValue!==t&&(this.oldValue=t,this._trigger("change")),t===this.options.max&&this._trigger("complete")}}),e.widget("ui.selectable",e.ui.mouse,{version:"1.11.4",options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch",selected:null,selecting:null,start:null,stop:null,unselected:null,unselecting:null},_create:function(){var t,i=this;this.element.addClass("ui-selectable"),this.dragged=!1,this.refresh=function(){t=e(i.options.filter,i.element[0]),t.addClass("ui-selectee"),t.each(function(){var t=e(this),i=t.offset();e.data(this,"selectable-item",{element:this,$element:t,left:i.left,top:i.top,right:i.left+t.outerWidth(),bottom:i.top+t.outerHeight(),startselected:!1,selected:t.hasClass("ui-selected"),selecting:t.hasClass("ui-selecting"),unselecting:t.hasClass("ui-unselecting")})})},this.refresh(),this.selectees=t.addClass("ui-selectee"),this._mouseInit(),this.helper=e("
      ")},_destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item"),this.element.removeClass("ui-selectable ui-selectable-disabled"),this._mouseDestroy()},_mouseStart:function(t){var i=this,s=this.options;this.opos=[t.pageX,t.pageY],this.options.disabled||(this.selectees=e(s.filter,this.element[0]),this._trigger("start",t),e(s.appendTo).append(this.helper),this.helper.css({left:t.pageX,top:t.pageY,width:0,height:0}),s.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var s=e.data(this,"selectable-item");s.startselected=!0,t.metaKey||t.ctrlKey||(s.$element.removeClass("ui-selected"),s.selected=!1,s.$element.addClass("ui-unselecting"),s.unselecting=!0,i._trigger("unselecting",t,{unselecting:s.element}))}),e(t.target).parents().addBack().each(function(){var s,n=e.data(this,"selectable-item");return n?(s=!t.metaKey&&!t.ctrlKey||!n.$element.hasClass("ui-selected"),n.$element.removeClass(s?"ui-unselecting":"ui-selected").addClass(s?"ui-selecting":"ui-unselecting"),n.unselecting=!s,n.selecting=s,n.selected=s,s?i._trigger("selecting",t,{selecting:n.element}):i._trigger("unselecting",t,{unselecting:n.element}),!1):void 0}))},_mouseDrag:function(t){if(this.dragged=!0,!this.options.disabled){var i,s=this,n=this.options,a=this.opos[0],o=this.opos[1],r=t.pageX,h=t.pageY;return a>r&&(i=r,r=a,a=i),o>h&&(i=h,h=o,o=i),this.helper.css({left:a,top:o,width:r-a,height:h-o}),this.selectees.each(function(){var i=e.data(this,"selectable-item"),l=!1;i&&i.element!==s.element[0]&&("touch"===n.tolerance?l=!(i.left>r||a>i.right||i.top>h||o>i.bottom):"fit"===n.tolerance&&(l=i.left>a&&r>i.right&&i.top>o&&h>i.bottom),l?(i.selected&&(i.$element.removeClass("ui-selected"),i.selected=!1),i.unselecting&&(i.$element.removeClass("ui-unselecting"),i.unselecting=!1),i.selecting||(i.$element.addClass("ui-selecting"),i.selecting=!0,s._trigger("selecting",t,{selecting:i.element}))):(i.selecting&&((t.metaKey||t.ctrlKey)&&i.startselected?(i.$element.removeClass("ui-selecting"),i.selecting=!1,i.$element.addClass("ui-selected"),i.selected=!0):(i.$element.removeClass("ui-selecting"),i.selecting=!1,i.startselected&&(i.$element.addClass("ui-unselecting"),i.unselecting=!0),s._trigger("unselecting",t,{unselecting:i.element}))),i.selected&&(t.metaKey||t.ctrlKey||i.startselected||(i.$element.removeClass("ui-selected"),i.selected=!1,i.$element.addClass("ui-unselecting"),i.unselecting=!0,s._trigger("unselecting",t,{unselecting:i.element})))))}),!1}},_mouseStop:function(t){var i=this;return this.dragged=!1,e(".ui-unselecting",this.element[0]).each(function(){var s=e.data(this,"selectable-item");s.$element.removeClass("ui-unselecting"),s.unselecting=!1,s.startselected=!1,i._trigger("unselected",t,{unselected:s.element})}),e(".ui-selecting",this.element[0]).each(function(){var s=e.data(this,"selectable-item");s.$element.removeClass("ui-selecting").addClass("ui-selected"),s.selecting=!1,s.selected=!0,s.startselected=!0,i._trigger("selected",t,{selected:s.element})}),this._trigger("stop",t),this.helper.remove(),!1}}),e.widget("ui.selectmenu",{version:"1.11.4",defaultElement:"",widgetEventPrefix:"spin",options:{culture:null,icons:{down:"ui-icon-triangle-1-s",up:"ui-icon-triangle-1-n"},incremental:!0,max:null,min:null,numberFormat:null,page:10,step:1,change:null,spin:null,start:null,stop:null},_create:function(){this._setOption("max",this.options.max),this._setOption("min",this.options.min),this._setOption("step",this.options.step),""!==this.value()&&this._value(this.element.val(),!0),this._draw(),this._on(this._events),this._refresh(),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_getCreateOptions:function(){var t={},i=this.element;return e.each(["min","max","step"],function(e,s){var n=i.attr(s);void 0!==n&&n.length&&(t[s]=n)}),t},_events:{keydown:function(e){this._start(e)&&this._keydown(e)&&e.preventDefault()},keyup:"_stop",focus:function(){this.previous=this.element.val()},blur:function(e){return this.cancelBlur?(delete this.cancelBlur,void 0):(this._stop(),this._refresh(),this.previous!==this.element.val()&&this._trigger("change",e),void 0)},mousewheel:function(e,t){if(t){if(!this.spinning&&!this._start(e))return!1;this._spin((t>0?1:-1)*this.options.step,e),clearTimeout(this.mousewheelTimer),this.mousewheelTimer=this._delay(function(){this.spinning&&this._stop(e)},100),e.preventDefault()}},"mousedown .ui-spinner-button":function(t){function i(){var e=this.element[0]===this.document[0].activeElement;e||(this.element.focus(),this.previous=s,this._delay(function(){this.previous=s}))}var s;s=this.element[0]===this.document[0].activeElement?this.previous:this.element.val(),t.preventDefault(),i.call(this),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur,i.call(this)}),this._start(t)!==!1&&this._repeat(null,e(t.currentTarget).hasClass("ui-spinner-up")?1:-1,t)},"mouseup .ui-spinner-button":"_stop","mouseenter .ui-spinner-button":function(t){return e(t.currentTarget).hasClass("ui-state-active")?this._start(t)===!1?!1:(this._repeat(null,e(t.currentTarget).hasClass("ui-spinner-up")?1:-1,t),void 0):void 0},"mouseleave .ui-spinner-button":"_stop"},_draw:function(){var e=this.uiSpinner=this.element.addClass("ui-spinner-input").attr("autocomplete","off").wrap(this._uiSpinnerHtml()).parent().append(this._buttonHtml());this.element.attr("role","spinbutton"),this.buttons=e.find(".ui-spinner-button").attr("tabIndex",-1).button().removeClass("ui-corner-all"),this.buttons.height()>Math.ceil(.5*e.height())&&e.height()>0&&e.height(e.height()),this.options.disabled&&this.disable()},_keydown:function(t){var i=this.options,s=e.ui.keyCode;switch(t.keyCode){case s.UP:return this._repeat(null,1,t),!0;case s.DOWN:return this._repeat(null,-1,t),!0;case s.PAGE_UP:return this._repeat(null,i.page,t),!0;case s.PAGE_DOWN:return this._repeat(null,-i.page,t),!0}return!1},_uiSpinnerHtml:function(){return""},_buttonHtml:function(){return""+""+""+""+""},_start:function(e){return this.spinning||this._trigger("start",e)!==!1?(this.counter||(this.counter=1),this.spinning=!0,!0):!1},_repeat:function(e,t,i){e=e||500,clearTimeout(this.timer),this.timer=this._delay(function(){this._repeat(40,t,i)},e),this._spin(t*this.options.step,i)},_spin:function(e,t){var i=this.value()||0;this.counter||(this.counter=1),i=this._adjustValue(i+e*this._increment(this.counter)),this.spinning&&this._trigger("spin",t,{value:i})===!1||(this._value(i),this.counter++)},_increment:function(t){var i=this.options.incremental;return i?e.isFunction(i)?i(t):Math.floor(t*t*t/5e4-t*t/500+17*t/200+1):1},_precision:function(){var e=this._precisionOf(this.options.step);return null!==this.options.min&&(e=Math.max(e,this._precisionOf(this.options.min))),e},_precisionOf:function(e){var t=""+e,i=t.indexOf(".");return-1===i?0:t.length-i-1},_adjustValue:function(e){var t,i,s=this.options;return t=null!==s.min?s.min:0,i=e-t,i=Math.round(i/s.step)*s.step,e=t+i,e=parseFloat(e.toFixed(this._precision())),null!==s.max&&e>s.max?s.max:null!==s.min&&s.min>e?s.min:e},_stop:function(e){this.spinning&&(clearTimeout(this.timer),clearTimeout(this.mousewheelTimer),this.counter=0,this.spinning=!1,this._trigger("stop",e))},_setOption:function(e,t){if("culture"===e||"numberFormat"===e){var i=this._parse(this.element.val());return this.options[e]=t,this.element.val(this._format(i)),void 0}("max"===e||"min"===e||"step"===e)&&"string"==typeof t&&(t=this._parse(t)),"icons"===e&&(this.buttons.first().find(".ui-icon").removeClass(this.options.icons.up).addClass(t.up),this.buttons.last().find(".ui-icon").removeClass(this.options.icons.down).addClass(t.down)),this._super(e,t),"disabled"===e&&(this.widget().toggleClass("ui-state-disabled",!!t),this.element.prop("disabled",!!t),this.buttons.button(t?"disable":"enable"))},_setOptions:h(function(e){this._super(e)}),_parse:function(e){return"string"==typeof e&&""!==e&&(e=window.Globalize&&this.options.numberFormat?Globalize.parseFloat(e,10,this.options.culture):+e),""===e||isNaN(e)?null:e},_format:function(e){return""===e?"":window.Globalize&&this.options.numberFormat?Globalize.format(e,this.options.numberFormat,this.options.culture):e},_refresh:function(){this.element.attr({"aria-valuemin":this.options.min,"aria-valuemax":this.options.max,"aria-valuenow":this._parse(this.element.val())})},isValid:function(){var e=this.value();return null===e?!1:e===this._adjustValue(e)},_value:function(e,t){var i;""!==e&&(i=this._parse(e),null!==i&&(t||(i=this._adjustValue(i)),e=this._format(i))),this.element.val(e),this._refresh()},_destroy:function(){this.element.removeClass("ui-spinner-input").prop("disabled",!1).removeAttr("autocomplete").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.uiSpinner.replaceWith(this.element)},stepUp:h(function(e){this._stepUp(e)}),_stepUp:function(e){this._start()&&(this._spin((e||1)*this.options.step),this._stop())},stepDown:h(function(e){this._stepDown(e)}),_stepDown:function(e){this._start()&&(this._spin((e||1)*-this.options.step),this._stop())},pageUp:h(function(e){this._stepUp((e||1)*this.options.page)}),pageDown:h(function(e){this._stepDown((e||1)*this.options.page)}),value:function(e){return arguments.length?(h(this._value).call(this,e),void 0):this._parse(this.element.val())},widget:function(){return this.uiSpinner}}),e.widget("ui.tabs",{version:"1.11.4",delay:300,options:{active:null,collapsible:!1,event:"click",heightStyle:"content",hide:null,show:null,activate:null,beforeActivate:null,beforeLoad:null,load:null},_isLocal:function(){var e=/#.*$/;return function(t){var i,s;t=t.cloneNode(!1),i=t.href.replace(e,""),s=location.href.replace(e,"");try{i=decodeURIComponent(i)}catch(n){}try{s=decodeURIComponent(s)}catch(n){}return t.hash.length>1&&i===s}}(),_create:function(){var t=this,i=this.options;this.running=!1,this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all").toggleClass("ui-tabs-collapsible",i.collapsible),this._processTabs(),i.active=this._initialActive(),e.isArray(i.disabled)&&(i.disabled=e.unique(i.disabled.concat(e.map(this.tabs.filter(".ui-state-disabled"),function(e){return t.tabs.index(e)}))).sort()),this.active=this.options.active!==!1&&this.anchors.length?this._findActive(i.active):e(),this._refresh(),this.active.length&&this.load(i.active)},_initialActive:function(){var t=this.options.active,i=this.options.collapsible,s=location.hash.substring(1);return null===t&&(s&&this.tabs.each(function(i,n){return e(n).attr("aria-controls")===s?(t=i,!1):void 0}),null===t&&(t=this.tabs.index(this.tabs.filter(".ui-tabs-active"))),(null===t||-1===t)&&(t=this.tabs.length?0:!1)),t!==!1&&(t=this.tabs.index(this.tabs.eq(t)),-1===t&&(t=i?!1:0)),!i&&t===!1&&this.anchors.length&&(t=0),t},_getCreateEventData:function(){return{tab:this.active,panel:this.active.length?this._getPanelForTab(this.active):e()}},_tabKeydown:function(t){var i=e(this.document[0].activeElement).closest("li"),s=this.tabs.index(i),n=!0;if(!this._handlePageNav(t)){switch(t.keyCode){case e.ui.keyCode.RIGHT:case e.ui.keyCode.DOWN:s++;break;case e.ui.keyCode.UP:case e.ui.keyCode.LEFT:n=!1,s--;break;case e.ui.keyCode.END:s=this.anchors.length-1;break;case e.ui.keyCode.HOME:s=0;break;case e.ui.keyCode.SPACE:return t.preventDefault(),clearTimeout(this.activating),this._activate(s),void 0;case e.ui.keyCode.ENTER:return t.preventDefault(),clearTimeout(this.activating),this._activate(s===this.options.active?!1:s),void 0;default:return}t.preventDefault(),clearTimeout(this.activating),s=this._focusNextTab(s,n),t.ctrlKey||t.metaKey||(i.attr("aria-selected","false"),this.tabs.eq(s).attr("aria-selected","true"),this.activating=this._delay(function(){this.option("active",s)},this.delay))}},_panelKeydown:function(t){this._handlePageNav(t)||t.ctrlKey&&t.keyCode===e.ui.keyCode.UP&&(t.preventDefault(),this.active.focus())},_handlePageNav:function(t){return t.altKey&&t.keyCode===e.ui.keyCode.PAGE_UP?(this._activate(this._focusNextTab(this.options.active-1,!1)),!0):t.altKey&&t.keyCode===e.ui.keyCode.PAGE_DOWN?(this._activate(this._focusNextTab(this.options.active+1,!0)),!0):void 0},_findNextTab:function(t,i){function s(){return t>n&&(t=0),0>t&&(t=n),t}for(var n=this.tabs.length-1;-1!==e.inArray(s(),this.options.disabled);)t=i?t+1:t-1;return t},_focusNextTab:function(e,t){return e=this._findNextTab(e,t),this.tabs.eq(e).focus(),e},_setOption:function(e,t){return"active"===e?(this._activate(t),void 0):"disabled"===e?(this._setupDisabled(t),void 0):(this._super(e,t),"collapsible"===e&&(this.element.toggleClass("ui-tabs-collapsible",t),t||this.options.active!==!1||this._activate(0)),"event"===e&&this._setupEvents(t),"heightStyle"===e&&this._setupHeightStyle(t),void 0)},_sanitizeSelector:function(e){return e?e.replace(/[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g,"\\$&"):""},refresh:function(){var t=this.options,i=this.tablist.children(":has(a[href])");t.disabled=e.map(i.filter(".ui-state-disabled"),function(e){return i.index(e)}),this._processTabs(),t.active!==!1&&this.anchors.length?this.active.length&&!e.contains(this.tablist[0],this.active[0])?this.tabs.length===t.disabled.length?(t.active=!1,this.active=e()):this._activate(this._findNextTab(Math.max(0,t.active-1),!1)):t.active=this.tabs.index(this.active):(t.active=!1,this.active=e()),this._refresh()},_refresh:function(){this._setupDisabled(this.options.disabled),this._setupEvents(this.options.event),this._setupHeightStyle(this.options.heightStyle),this.tabs.not(this.active).attr({"aria-selected":"false","aria-expanded":"false",tabIndex:-1}),this.panels.not(this._getPanelForTab(this.active)).hide().attr({"aria-hidden":"true"}),this.active.length?(this.active.addClass("ui-tabs-active ui-state-active").attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0}),this._getPanelForTab(this.active).show().attr({"aria-hidden":"false"})):this.tabs.eq(0).attr("tabIndex",0)},_processTabs:function(){var t=this,i=this.tabs,s=this.anchors,n=this.panels; +this.tablist=this._getList().addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").attr("role","tablist").delegate("> li","mousedown"+this.eventNamespace,function(t){e(this).is(".ui-state-disabled")&&t.preventDefault()}).delegate(".ui-tabs-anchor","focus"+this.eventNamespace,function(){e(this).closest("li").is(".ui-state-disabled")&&this.blur()}),this.tabs=this.tablist.find("> li:has(a[href])").addClass("ui-state-default ui-corner-top").attr({role:"tab",tabIndex:-1}),this.anchors=this.tabs.map(function(){return e("a",this)[0]}).addClass("ui-tabs-anchor").attr({role:"presentation",tabIndex:-1}),this.panels=e(),this.anchors.each(function(i,s){var n,a,o,r=e(s).uniqueId().attr("id"),h=e(s).closest("li"),l=h.attr("aria-controls");t._isLocal(s)?(n=s.hash,o=n.substring(1),a=t.element.find(t._sanitizeSelector(n))):(o=h.attr("aria-controls")||e({}).uniqueId()[0].id,n="#"+o,a=t.element.find(n),a.length||(a=t._createPanel(o),a.insertAfter(t.panels[i-1]||t.tablist)),a.attr("aria-live","polite")),a.length&&(t.panels=t.panels.add(a)),l&&h.data("ui-tabs-aria-controls",l),h.attr({"aria-controls":o,"aria-labelledby":r}),a.attr("aria-labelledby",r)}),this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").attr("role","tabpanel"),i&&(this._off(i.not(this.tabs)),this._off(s.not(this.anchors)),this._off(n.not(this.panels)))},_getList:function(){return this.tablist||this.element.find("ol,ul").eq(0)},_createPanel:function(t){return e("
      ").attr("id",t).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy",!0)},_setupDisabled:function(t){e.isArray(t)&&(t.length?t.length===this.anchors.length&&(t=!0):t=!1);for(var i,s=0;i=this.tabs[s];s++)t===!0||-1!==e.inArray(s,t)?e(i).addClass("ui-state-disabled").attr("aria-disabled","true"):e(i).removeClass("ui-state-disabled").removeAttr("aria-disabled");this.options.disabled=t},_setupEvents:function(t){var i={};t&&e.each(t.split(" "),function(e,t){i[t]="_eventHandler"}),this._off(this.anchors.add(this.tabs).add(this.panels)),this._on(!0,this.anchors,{click:function(e){e.preventDefault()}}),this._on(this.anchors,i),this._on(this.tabs,{keydown:"_tabKeydown"}),this._on(this.panels,{keydown:"_panelKeydown"}),this._focusable(this.tabs),this._hoverable(this.tabs)},_setupHeightStyle:function(t){var i,s=this.element.parent();"fill"===t?(i=s.height(),i-=this.element.outerHeight()-this.element.height(),this.element.siblings(":visible").each(function(){var t=e(this),s=t.css("position");"absolute"!==s&&"fixed"!==s&&(i-=t.outerHeight(!0))}),this.element.children().not(this.panels).each(function(){i-=e(this).outerHeight(!0)}),this.panels.each(function(){e(this).height(Math.max(0,i-e(this).innerHeight()+e(this).height()))}).css("overflow","auto")):"auto"===t&&(i=0,this.panels.each(function(){i=Math.max(i,e(this).height("").height())}).height(i))},_eventHandler:function(t){var i=this.options,s=this.active,n=e(t.currentTarget),a=n.closest("li"),o=a[0]===s[0],r=o&&i.collapsible,h=r?e():this._getPanelForTab(a),l=s.length?this._getPanelForTab(s):e(),u={oldTab:s,oldPanel:l,newTab:r?e():a,newPanel:h};t.preventDefault(),a.hasClass("ui-state-disabled")||a.hasClass("ui-tabs-loading")||this.running||o&&!i.collapsible||this._trigger("beforeActivate",t,u)===!1||(i.active=r?!1:this.tabs.index(a),this.active=o?e():a,this.xhr&&this.xhr.abort(),l.length||h.length||e.error("jQuery UI Tabs: Mismatching fragment identifier."),h.length&&this.load(this.tabs.index(a),t),this._toggle(t,u))},_toggle:function(t,i){function s(){a.running=!1,a._trigger("activate",t,i)}function n(){i.newTab.closest("li").addClass("ui-tabs-active ui-state-active"),o.length&&a.options.show?a._show(o,a.options.show,s):(o.show(),s())}var a=this,o=i.newPanel,r=i.oldPanel;this.running=!0,r.length&&this.options.hide?this._hide(r,this.options.hide,function(){i.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),n()}):(i.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),r.hide(),n()),r.attr("aria-hidden","true"),i.oldTab.attr({"aria-selected":"false","aria-expanded":"false"}),o.length&&r.length?i.oldTab.attr("tabIndex",-1):o.length&&this.tabs.filter(function(){return 0===e(this).attr("tabIndex")}).attr("tabIndex",-1),o.attr("aria-hidden","false"),i.newTab.attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0})},_activate:function(t){var i,s=this._findActive(t);s[0]!==this.active[0]&&(s.length||(s=this.active),i=s.find(".ui-tabs-anchor")[0],this._eventHandler({target:i,currentTarget:i,preventDefault:e.noop}))},_findActive:function(t){return t===!1?e():this.tabs.eq(t)},_getIndex:function(e){return"string"==typeof e&&(e=this.anchors.index(this.anchors.filter("[href$='"+e+"']"))),e},_destroy:function(){this.xhr&&this.xhr.abort(),this.element.removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible"),this.tablist.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").removeAttr("role"),this.anchors.removeClass("ui-tabs-anchor").removeAttr("role").removeAttr("tabIndex").removeUniqueId(),this.tablist.unbind(this.eventNamespace),this.tabs.add(this.panels).each(function(){e.data(this,"ui-tabs-destroy")?e(this).remove():e(this).removeClass("ui-state-default ui-state-active ui-state-disabled ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel").removeAttr("tabIndex").removeAttr("aria-live").removeAttr("aria-busy").removeAttr("aria-selected").removeAttr("aria-labelledby").removeAttr("aria-hidden").removeAttr("aria-expanded").removeAttr("role")}),this.tabs.each(function(){var t=e(this),i=t.data("ui-tabs-aria-controls");i?t.attr("aria-controls",i).removeData("ui-tabs-aria-controls"):t.removeAttr("aria-controls")}),this.panels.show(),"content"!==this.options.heightStyle&&this.panels.css("height","")},enable:function(t){var i=this.options.disabled;i!==!1&&(void 0===t?i=!1:(t=this._getIndex(t),i=e.isArray(i)?e.map(i,function(e){return e!==t?e:null}):e.map(this.tabs,function(e,i){return i!==t?i:null})),this._setupDisabled(i))},disable:function(t){var i=this.options.disabled;if(i!==!0){if(void 0===t)i=!0;else{if(t=this._getIndex(t),-1!==e.inArray(t,i))return;i=e.isArray(i)?e.merge([t],i).sort():[t]}this._setupDisabled(i)}},load:function(t,i){t=this._getIndex(t);var s=this,n=this.tabs.eq(t),a=n.find(".ui-tabs-anchor"),o=this._getPanelForTab(n),r={tab:n,panel:o},h=function(e,t){"abort"===t&&s.panels.stop(!1,!0),n.removeClass("ui-tabs-loading"),o.removeAttr("aria-busy"),e===s.xhr&&delete s.xhr};this._isLocal(a[0])||(this.xhr=e.ajax(this._ajaxSettings(a,i,r)),this.xhr&&"canceled"!==this.xhr.statusText&&(n.addClass("ui-tabs-loading"),o.attr("aria-busy","true"),this.xhr.done(function(e,t,n){setTimeout(function(){o.html(e),s._trigger("load",i,r),h(n,t)},1)}).fail(function(e,t){setTimeout(function(){h(e,t)},1)})))},_ajaxSettings:function(t,i,s){var n=this;return{url:t.attr("href"),beforeSend:function(t,a){return n._trigger("beforeLoad",i,e.extend({jqXHR:t,ajaxSettings:a},s))}}},_getPanelForTab:function(t){var i=e(t).attr("aria-controls");return this.element.find(this._sanitizeSelector("#"+i))}}),e.widget("ui.tooltip",{version:"1.11.4",options:{content:function(){var t=e(this).attr("title")||"";return e("").text(t).html()},hide:!0,items:"[title]:not([disabled])",position:{my:"left top+15",at:"left bottom",collision:"flipfit flip"},show:!0,tooltipClass:null,track:!1,close:null,open:null},_addDescribedBy:function(t,i){var s=(t.attr("aria-describedby")||"").split(/\s+/);s.push(i),t.data("ui-tooltip-id",i).attr("aria-describedby",e.trim(s.join(" ")))},_removeDescribedBy:function(t){var i=t.data("ui-tooltip-id"),s=(t.attr("aria-describedby")||"").split(/\s+/),n=e.inArray(i,s);-1!==n&&s.splice(n,1),t.removeData("ui-tooltip-id"),s=e.trim(s.join(" ")),s?t.attr("aria-describedby",s):t.removeAttr("aria-describedby")},_create:function(){this._on({mouseover:"open",focusin:"open"}),this.tooltips={},this.parents={},this.options.disabled&&this._disable(),this.liveRegion=e("
      ").attr({role:"log","aria-live":"assertive","aria-relevant":"additions"}).addClass("ui-helper-hidden-accessible").appendTo(this.document[0].body)},_setOption:function(t,i){var s=this;return"disabled"===t?(this[i?"_disable":"_enable"](),this.options[t]=i,void 0):(this._super(t,i),"content"===t&&e.each(this.tooltips,function(e,t){s._updateContent(t.element)}),void 0)},_disable:function(){var t=this;e.each(this.tooltips,function(i,s){var n=e.Event("blur");n.target=n.currentTarget=s.element[0],t.close(n,!0)}),this.element.find(this.options.items).addBack().each(function(){var t=e(this);t.is("[title]")&&t.data("ui-tooltip-title",t.attr("title")).removeAttr("title")})},_enable:function(){this.element.find(this.options.items).addBack().each(function(){var t=e(this);t.data("ui-tooltip-title")&&t.attr("title",t.data("ui-tooltip-title"))})},open:function(t){var i=this,s=e(t?t.target:this.element).closest(this.options.items);s.length&&!s.data("ui-tooltip-id")&&(s.attr("title")&&s.data("ui-tooltip-title",s.attr("title")),s.data("ui-tooltip-open",!0),t&&"mouseover"===t.type&&s.parents().each(function(){var t,s=e(this);s.data("ui-tooltip-open")&&(t=e.Event("blur"),t.target=t.currentTarget=this,i.close(t,!0)),s.attr("title")&&(s.uniqueId(),i.parents[this.id]={element:this,title:s.attr("title")},s.attr("title",""))}),this._registerCloseHandlers(t,s),this._updateContent(s,t))},_updateContent:function(e,t){var i,s=this.options.content,n=this,a=t?t.type:null;return"string"==typeof s?this._open(t,e,s):(i=s.call(e[0],function(i){n._delay(function(){e.data("ui-tooltip-open")&&(t&&(t.type=a),this._open(t,e,i))})}),i&&this._open(t,e,i),void 0)},_open:function(t,i,s){function n(e){l.of=e,o.is(":hidden")||o.position(l)}var a,o,r,h,l=e.extend({},this.options.position);if(s){if(a=this._find(i))return a.tooltip.find(".ui-tooltip-content").html(s),void 0;i.is("[title]")&&(t&&"mouseover"===t.type?i.attr("title",""):i.removeAttr("title")),a=this._tooltip(i),o=a.tooltip,this._addDescribedBy(i,o.attr("id")),o.find(".ui-tooltip-content").html(s),this.liveRegion.children().hide(),s.clone?(h=s.clone(),h.removeAttr("id").find("[id]").removeAttr("id")):h=s,e("
      ").html(h).appendTo(this.liveRegion),this.options.track&&t&&/^mouse/.test(t.type)?(this._on(this.document,{mousemove:n}),n(t)):o.position(e.extend({of:i},this.options.position)),o.hide(),this._show(o,this.options.show),this.options.show&&this.options.show.delay&&(r=this.delayedShow=setInterval(function(){o.is(":visible")&&(n(l.of),clearInterval(r))},e.fx.interval)),this._trigger("open",t,{tooltip:o})}},_registerCloseHandlers:function(t,i){var s={keyup:function(t){if(t.keyCode===e.ui.keyCode.ESCAPE){var s=e.Event(t);s.currentTarget=i[0],this.close(s,!0)}}};i[0]!==this.element[0]&&(s.remove=function(){this._removeTooltip(this._find(i).tooltip)}),t&&"mouseover"!==t.type||(s.mouseleave="close"),t&&"focusin"!==t.type||(s.focusout="close"),this._on(!0,i,s)},close:function(t){var i,s=this,n=e(t?t.currentTarget:this.element),a=this._find(n);return a?(i=a.tooltip,a.closing||(clearInterval(this.delayedShow),n.data("ui-tooltip-title")&&!n.attr("title")&&n.attr("title",n.data("ui-tooltip-title")),this._removeDescribedBy(n),a.hiding=!0,i.stop(!0),this._hide(i,this.options.hide,function(){s._removeTooltip(e(this))}),n.removeData("ui-tooltip-open"),this._off(n,"mouseleave focusout keyup"),n[0]!==this.element[0]&&this._off(n,"remove"),this._off(this.document,"mousemove"),t&&"mouseleave"===t.type&&e.each(this.parents,function(t,i){e(i.element).attr("title",i.title),delete s.parents[t]}),a.closing=!0,this._trigger("close",t,{tooltip:i}),a.hiding||(a.closing=!1)),void 0):(n.removeData("ui-tooltip-open"),void 0)},_tooltip:function(t){var i=e("
      ").attr("role","tooltip").addClass("ui-tooltip ui-widget ui-corner-all ui-widget-content "+(this.options.tooltipClass||"")),s=i.uniqueId().attr("id");return e("
      ").addClass("ui-tooltip-content").appendTo(i),i.appendTo(this.document[0].body),this.tooltips[s]={element:t,tooltip:i}},_find:function(e){var t=e.data("ui-tooltip-id");return t?this.tooltips[t]:null},_removeTooltip:function(e){e.remove(),delete this.tooltips[e.attr("id")]},_destroy:function(){var t=this;e.each(this.tooltips,function(i,s){var n=e.Event("blur"),a=s.element;n.target=n.currentTarget=a[0],t.close(n,!0),e("#"+i).remove(),a.data("ui-tooltip-title")&&(a.attr("title")||a.attr("title",a.data("ui-tooltip-title")),a.removeData("ui-tooltip-title"))}),this.liveRegion.remove()}})}); \ No newline at end of file diff --git a/visualisations/JsRoot460/scripts/jquery.min.js b/visualisations/JsRoot460/scripts/jquery.min.js new file mode 100644 index 0000000..49990d6 --- /dev/null +++ b/visualisations/JsRoot460/scripts/jquery.min.js @@ -0,0 +1,4 @@ +/*! jQuery v2.1.4 | (c) 2005, 2015 jQuery Foundation, Inc. | jquery.org/license */ +!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l=a.document,m="2.1.4",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){return!n.isArray(a)&&a-parseFloat(a)+1>=0},isPlainObject:function(a){return"object"!==n.type(a)||a.nodeType||n.isWindow(a)?!1:a.constructor&&!j.call(a.constructor.prototype,"isPrototypeOf")?!1:!0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=l.createElement("script"),b.text=a,l.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:g.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(e=d.call(arguments,2),f=function(){return a.apply(b||this,e.concat(d.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:k}),n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b="length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,aa=/[+~]/,ba=/'|\\/g,ca=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),da=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ea=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fa){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(ba,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+ra(o[l]);w=aa.test(a)&&pa(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",ea,!1):e.attachEvent&&e.attachEvent("onunload",ea)),p=!f(g),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?la(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ca,da),a[3]=(a[3]||a[4]||a[5]||"").replace(ca,da),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ca,da).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(ca,da),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return W.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(ca,da).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:oa(function(){return[0]}),last:oa(function(a,b){return[b-1]}),eq:oa(function(a,b,c){return[0>c?c+b:c]}),even:oa(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:oa(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:oa(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:oa(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function sa(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function ta(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ua(a,b,c){for(var d=0,e=b.length;e>d;d++)ga(a,b[d],c);return c}function va(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wa(a,b,c,d,e,f){return d&&!d[u]&&(d=wa(d)),e&&!e[u]&&(e=wa(e,f)),ia(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ua(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:va(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=va(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=va(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sa(function(a){return a===b},h,!0),l=sa(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sa(ta(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wa(i>1&&ta(m),i>1&&ra(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xa(a.slice(i,e)),f>e&&xa(a=a.slice(e)),f>e&&ra(a))}m.push(c)}return ta(m)}function ya(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=va(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&ga.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,ya(e,d)),f.selector=a}return f},i=ga.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ca,da),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ca,da),aa.test(j[0].type)&&pa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&ra(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,aa.test(a)&&pa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ja(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return g.call(b,a)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=n.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:l,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}return d=l.getElementById(c[2]),d&&d.parentNode&&(this.length=1,this[0]=d),this.context=l,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};A.prototype=n.fn,y=n(l);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?"string"==typeof a?g.call(n(a),this[0]):g.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,"parentNode")},parentsUntil:function(a,b,c){return n.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return n.dir(a,"nextSibling")},prevAll:function(a){return n.dir(a,"previousSibling")},nextUntil:function(a,b,c){return n.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return n.dir(a,"previousSibling",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(C[a]||n.unique(e),B.test(a)&&e.reverse()),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return n.each(a.match(E)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(b=a.memory&&l,c=!0,g=e||0,e=0,f=h.length,d=!0;h&&f>g;g++)if(h[g].apply(l[0],l[1])===!1&&a.stopOnFalse){b=!1;break}d=!1,h&&(i?i.length&&j(i.shift()):b?h=[]:k.disable())},k={add:function(){if(h){var c=h.length;!function g(b){n.each(b,function(b,c){var d=n.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&g(c)})}(arguments),d?f=h.length:b&&(e=c,j(b))}return this},remove:function(){return h&&n.each(arguments,function(a,b){var c;while((c=n.inArray(b,h,c))>-1)h.splice(c,1),d&&(f>=c&&f--,g>=c&&g--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],f=0,this},disable:function(){return h=i=b=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,b||k.disable(),this},locked:function(){return!i},fireWith:function(a,b){return!h||c&&!i||(b=b||[],b=[a,b.slice?b.slice():b],d?i.push(b):j(b)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!c}};return k},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&n.isFunction(a.promise)?e:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(H.resolveWith(l,[n]),n.fn.triggerHandler&&(n(l).triggerHandler("ready"),n(l).off("ready"))))}});function I(){l.removeEventListener("DOMContentLoaded",I,!1),a.removeEventListener("load",I,!1),n.ready()}n.ready.promise=function(b){return H||(H=n.Deferred(),"complete"===l.readyState?setTimeout(n.ready):(l.addEventListener("DOMContentLoaded",I,!1),a.addEventListener("load",I,!1))),H.promise(b)},n.ready.promise();var J=n.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)n.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f};n.acceptData=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function K(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=n.expando+K.uid++}K.uid=1,K.accepts=n.acceptData,K.prototype={key:function(a){if(!K.accepts(a))return 0;var b={},c=a[this.expando];if(!c){c=K.uid++;try{b[this.expando]={value:c},Object.defineProperties(a,b)}catch(d){b[this.expando]=c,n.extend(a,b)}}return this.cache[c]||(this.cache[c]={}),c},set:function(a,b,c){var d,e=this.key(a),f=this.cache[e];if("string"==typeof b)f[b]=c;else if(n.isEmptyObject(f))n.extend(this.cache[e],b);else for(d in b)f[d]=b[d];return f},get:function(a,b){var c=this.cache[this.key(a)];return void 0===b?c:c[b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=this.key(a),g=this.cache[f];if(void 0===b)this.cache[f]={};else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in g?d=[b,e]:(d=e,d=d in g?[d]:d.match(E)||[])),c=d.length;while(c--)delete g[d[c]]}},hasData:function(a){return!n.isEmptyObject(this.cache[a[this.expando]]||{})},discard:function(a){a[this.expando]&&delete this.cache[a[this.expando]]}};var L=new K,M=new K,N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(O,"-$1").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}M.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return M.hasData(a)||L.hasData(a)},data:function(a,b,c){ +return M.access(a,b,c)},removeData:function(a,b){M.remove(a,b)},_data:function(a,b,c){return L.access(a,b,c)},_removeData:function(a,b){L.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=M.get(f),1===f.nodeType&&!L.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));L.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){M.set(this,a)}):J(this,function(b){var c,d=n.camelCase(a);if(f&&void 0===b){if(c=M.get(f,a),void 0!==c)return c;if(c=M.get(f,d),void 0!==c)return c;if(c=P(f,d,void 0),void 0!==c)return c}else this.each(function(){var c=M.get(this,d);M.set(this,d,b),-1!==a.indexOf("-")&&void 0!==c&&M.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){M.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=L.get(a,b),c&&(!d||n.isArray(c)?d=L.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return L.get(a,c)||L.access(a,c,{empty:n.Callbacks("once memory").add(function(){L.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthx",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U="undefined";k.focusinBubbles="onfocusin"in a;var V=/^key/,W=/^(?:mouse|pointer|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return l.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof n!==U&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(E)||[""],j=b.length;while(j--)h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g,!1)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&(delete r.handle,L.remove(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,m,o,p=[d||l],q=j.call(b,"type")?b.type:b,r=j.call(b,"namespace")?b.namespace.split("."):[];if(g=h=d=d||l,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+n.event.triggered)&&(q.indexOf(".")>=0&&(r=q.split("."),q=r.shift(),r.sort()),k=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=r.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},e||!o.trigger||o.trigger.apply(d,c)!==!1)){if(!e&&!o.noBubble&&!n.isWindow(d)){for(i=o.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||l)&&p.push(h.defaultView||h.parentWindow||a)}f=0;while((g=p[f++])&&!b.isPropagationStopped())b.type=f>1?i:o.bindType||q,m=(L.get(g,"events")||{})[b.type]&&L.get(g,"handle"),m&&m.apply(g,c),m=k&&g[k],m&&m.apply&&n.acceptData(g)&&(b.result=m.apply(g,c),b.result===!1&&b.preventDefault());return b.type=q,e||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!n.acceptData(d)||k&&n.isFunction(d[q])&&!n.isWindow(d)&&(h=d[k],h&&(d[k]=null),n.event.triggered=q,d[q](),n.event.triggered=void 0,h&&(d[k]=h)),b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(L.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(g.namespace))&&(a.handleObj=g,a.data=g.data,e=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(a.result=e)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!==this;i=i.parentNode||this)if(i.disabled!==!0||"click"!==a.type){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>=0:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]*)\/>/gi,ba=/<([\w:]+)/,ca=/<|&#?\w+;/,da=/<(?:script|style|link)/i,ea=/checked\s*(?:[^=]|=\s*.checked.)/i,fa=/^$|\/(?:java|ecma)script/i,ga=/^true\/(.*)/,ha=/^\s*\s*$/g,ia={option:[1,""],thead:[1,"","
      "],col:[2,"","
      "],tr:[2,"","
      "],td:[3,"","
      "],_default:[0,"",""]};ia.optgroup=ia.option,ia.tbody=ia.tfoot=ia.colgroup=ia.caption=ia.thead,ia.th=ia.td;function ja(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function ka(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function la(a){var b=ga.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function ma(a,b){for(var c=0,d=a.length;d>c;c++)L.set(a[c],"globalEval",!b||L.get(b[c],"globalEval"))}function na(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(L.hasData(a)&&(f=L.access(a),g=L.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}M.hasData(a)&&(h=M.access(a),i=n.extend({},h),M.set(b,i))}}function oa(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||"*"):a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function pa(a,b){var c=b.nodeName.toLowerCase();"input"===c&&T.test(a.type)?b.checked=a.checked:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}n.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=oa(h),f=oa(a),d=0,e=f.length;e>d;d++)pa(f[d],g[d]);if(b)if(c)for(f=f||oa(a),g=g||oa(h),d=0,e=f.length;e>d;d++)na(f[d],g[d]);else na(a,h);return g=oa(h,"script"),g.length>0&&ma(g,!i&&oa(a,"script")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,o=a.length;o>m;m++)if(e=a[m],e||0===e)if("object"===n.type(e))n.merge(l,e.nodeType?[e]:e);else if(ca.test(e)){f=f||k.appendChild(b.createElement("div")),g=(ba.exec(e)||["",""])[1].toLowerCase(),h=ia[g]||ia._default,f.innerHTML=h[1]+e.replace(aa,"<$1>")+h[2],j=h[0];while(j--)f=f.lastChild;n.merge(l,f.childNodes),f=k.firstChild,f.textContent=""}else l.push(b.createTextNode(e));k.textContent="",m=0;while(e=l[m++])if((!d||-1===n.inArray(e,d))&&(i=n.contains(e.ownerDocument,e),f=oa(k.appendChild(e),"script"),i&&ma(f),c)){j=0;while(e=f[j++])fa.test(e.type||"")&&c.push(e)}return k},cleanData:function(a){for(var b,c,d,e,f=n.event.special,g=0;void 0!==(c=a[g]);g++){if(n.acceptData(c)&&(e=c[L.expando],e&&(b=L.cache[e]))){if(b.events)for(d in b.events)f[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);L.cache[e]&&delete L.cache[e]}delete M.cache[c[M.expando]]}}}),n.fn.extend({text:function(a){return J(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=a)})},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=ja(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=ja(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(oa(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&ma(oa(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(oa(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return J(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!da.test(a)&&!ia[(ba.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(aa,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(oa(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(oa(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,m=this,o=l-1,p=a[0],q=n.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&ea.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(c=n.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(f=n.map(oa(c,"script"),ka),g=f.length;l>j;j++)h=c,j!==o&&(h=n.clone(h,!0,!0),g&&n.merge(f,oa(h,"script"))),b.call(this[j],h,j);if(g)for(i=f[f.length-1].ownerDocument,n.map(f,la),j=0;g>j;j++)h=f[j],fa.test(h.type||"")&&!L.access(h,"globalEval")&&n.contains(i,h)&&(h.src?n._evalUrl&&n._evalUrl(h.src):n.globalEval(h.textContent.replace(ha,"")))}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),g=e.length-1,h=0;g>=h;h++)c=h===g?this:this.clone(!0),n(e[h])[b](c),f.apply(d,c.get());return this.pushStack(d)}});var qa,ra={};function sa(b,c){var d,e=n(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:n.css(e[0],"display");return e.detach(),f}function ta(a){var b=l,c=ra[a];return c||(c=sa(a,b),"none"!==c&&c||(qa=(qa||n(" -
      + Get Started - Histograms Analyser @@ -37,7 +45,7 @@
      - +

      (...it can take few seconds, please wait :)

      diff --git a/visualisations/documentation.php b/visualisations/documentation.php index 40974d5..e4133c1 100644 --- a/visualisations/documentation.php +++ b/visualisations/documentation.php @@ -17,7 +17,7 @@
      - +
      @@ -47,7 +47,7 @@
      -

      ...or read, download and more directly

      +

      ...or read it, download it and more

      in GitBook

      diff --git a/visualisations/index.php b/visualisations/index.php index cefd61f..17407ca 100644 --- a/visualisations/index.php +++ b/visualisations/index.php @@ -29,7 +29,10 @@
      - Visualisations + Visualisations +
      + +
      @@ -52,8 +55,8 @@
      - - + +
      diff --git a/visualisations/live-events.php b/visualisations/live-events.php index 6fa1079..532a770 100644 --- a/visualisations/live-events.php +++ b/visualisations/live-events.php @@ -12,12 +12,16 @@
      - Get Startted - Live +

      + Public ATLAS display of real events! + Check some of the events coming from the ATLAS detector right now. +

      +

      + Do you want to know more? Check the Documentation +

      -
      - -
      + Get Startted - Live
      @@ -36,7 +40,7 @@
      - +
      diff --git a/visualisations/root-browser.php b/visualisations/root-browser.php index 6eee14b..e611451 100644 --- a/visualisations/root-browser.php +++ b/visualisations/root-browser.php @@ -13,12 +13,17 @@
      - Get Started - Histograms App Analyser +

      + Look into ROOT files! + A web based tool for displaying and analysing data and Monte-Carlo simulated data. + Select a dataset using the drop-down menu (second text box). +

      +

      + Do you want to know more? Check the Documentation +

      -
      - -
      + Get Started - Histograms App Analyser
      @@ -37,7 +42,7 @@
      - +
      - +
      diff --git a/webanalysis/ROOTbooks.php b/webanalysis/ROOTbooks.php index d97f68a..f93f396 100644 --- a/webanalysis/ROOTbooks.php +++ b/webanalysis/ROOTbooks.php @@ -12,13 +12,20 @@ -
      - Web Analysis - ROOTbooks + +

      + The ATLAS Experiment has made 7 analyses available to help you get started with your own research! + We are producing ROOT notebooks (ROOTbooks) for them as well. Avoid local installations by using notebooks in a Software as a Service environment on your computer or in the Cloud. +
      + Check our examples in the Official ROOT gallery or in the Jupyter Viewer for an even easier access. + Run, edit and save ROOTbooks. Use our examples to explore the public datasets and create your own ROOTbooks directly in your browser! +

      +

      + Do you want to know more? Check the Documentation +

      -
      - -
      + Web Analysis - ROOTbooks
      diff --git a/webanalysis/documentation.php b/webanalysis/documentation.php index 8281439..0d47218 100644 --- a/webanalysis/documentation.php +++ b/webanalysis/documentation.php @@ -17,7 +17,7 @@
      - +
      @@ -46,7 +46,7 @@
      -

      ...or read, download and more directly

      +

      ...or read it, download it and more

      in GitBook

      diff --git a/webanalysis/index.php b/webanalysis/index.php index 85b6840..45b4b75 100644 --- a/webanalysis/index.php +++ b/webanalysis/index.php @@ -14,12 +14,12 @@

      The ATLAS Experiment has made 7 analyses available to help you get started with your own research! These analyses range from measuring Standard Model particles, hunt for the Higgs boson, and even search for physics Beyond the Standard Model particle. - Now we are in the process of making ROOT notebooks (ROOTbooks) for them as well. Avoid local installations by using notebooks in a Software as a Service environment on your computer or in the Cloud. + We are producing ROOT notebooks (ROOTbooks) for them as well.

      Explore:

      -
        +
        • Documentation: a step-by-step guide to using, creating and executing ROOT notebooks
        • ROOTbooks: use Jupyter technology and the power of ROOT to review, execute and develop your own analysis directly in your browser
        • Execute ROOTbooks: run, edit and save ROOTbooks. Use our examples to explore the public datasets. You can create your own ROOTbooks as well!
        • @@ -27,7 +27,10 @@
          - Web Analysis + Web Analysis +
          + +
          @@ -35,7 +38,6 @@
      -

      Explore