00001
00002
00003
00004 (function() {
00005
00006 if (typeof JSROOT != 'object') {
00007 var e1 = new Error('JSROOT is not defined');
00008 e1.source = 'JSRoot3DPainter.js';
00009 throw e1;
00010 }
00011
00012 if (typeof d3 != 'object') {
00013 var e1 = new Error('This extension requires d3.v3.js');
00014 e1.source = 'JSRoot3DPainter.js';
00015 throw e1;
00016 }
00017
00018 if (typeof JSROOT.Painter != 'object') {
00019 var e1 = new Error('JSROOT.Painter is not defined');
00020 e1.source = 'JSRoot3DPainter.js';
00021 throw e1;
00022 }
00023
00024 JSROOT.Painter.add3DInteraction = function(renderer, scene, camera, toplevel, painter) {
00025
00026 var mouseX, mouseY, mouseDowned = false;
00027 var mouse = { x : 0, y : 0 }, INTERSECTED;
00028
00029 var tooltip = function() {
00030 var id = 'tt';
00031 var top = 3;
00032 var left = 3;
00033 var maxw = 150;
00034 var speed = 10;
00035 var timer = 20;
00036 var endalpha = 95;
00037 var alpha = 0;
00038 var tt, t, c, b, h;
00039 var ie = document.all ? true : false;
00040 return {
00041 show : function(v, w) {
00042 if (tt == null) {
00043 tt = document.createElement('div');
00044 tt.setAttribute('id', id);
00045 t = document.createElement('div');
00046 t.setAttribute('id', id + 'top');
00047 c = document.createElement('div');
00048 c.setAttribute('id', id + 'cont');
00049 b = document.createElement('div');
00050 b.setAttribute('id', id + 'bot');
00051 tt.appendChild(t);
00052 tt.appendChild(c);
00053 tt.appendChild(b);
00054 document.body.appendChild(tt);
00055 tt.style.opacity = 0;
00056 tt.style.filter = 'alpha(opacity=0)';
00057 document.onmousemove = this.pos;
00058 }
00059 tt.style.display = 'block';
00060 c.innerHTML = v;
00061 tt.style.width = w ? w + 'px' : 'auto';
00062 tt.style.width = 'auto';
00063 if (!w && ie) {
00064 t.style.display = 'none';
00065 b.style.display = 'none';
00066 tt.style.width = tt.offsetWidth;
00067 t.style.display = 'block';
00068 b.style.display = 'block';
00069 }
00070
00071 h = parseInt(tt.offsetHeight) + top;
00072 clearInterval(tt.timer);
00073 tt.timer = setInterval(function() { tooltip.fade(1) }, timer);
00074 },
00075 pos : function(e) {
00076 var u = ie ? event.clientY + document.documentElement.scrollTop : e.pageY;
00077 var l = ie ? event.clientX + document.documentElement.scrollLeft : e.pageX;
00078 tt.style.top = u + 15 + 'px';
00079 tt.style.left = (l + left) + 'px';
00080 },
00081 fade : function(d) {
00082 var a = alpha;
00083 if ((a != endalpha && d == 1) || (a != 0 && d == -1)) {
00084 var i = speed;
00085 if (endalpha - a < speed && d == 1) {
00086 i = endalpha - a;
00087 } else if (alpha < speed && d == -1) {
00088 i = a;
00089 }
00090 alpha = a + (i * d);
00091 tt.style.opacity = alpha * .01;
00092 tt.style.filter = 'alpha(opacity=' + alpha + ')';
00093 } else {
00094 clearInterval(tt.timer);
00095 if (d == -1) {
00096 tt.style.display = 'none';
00097 }
00098 }
00099 },
00100 hide : function() {
00101 if (tt == null)
00102 return;
00103 clearInterval(tt.timer);
00104 tt.timer = setInterval(function() {
00105 tooltip.fade(-1);
00106 }, timer);
00107 }
00108 };
00109 }();
00110
00111 var radius = 100;
00112 var theta = 0;
00113 var projector = new THREE.Projector();
00114 function findIntersection() {
00115
00116 if (mouseDowned) {
00117 if (INTERSECTED) {
00118 INTERSECTED.material.emissive.setHex(INTERSECTED.currentHex);
00119 renderer.render(scene, camera);
00120 }
00121 INTERSECTED = null;
00122 if (JSROOT.gStyle.Tooltip)
00123 tooltip.hide();
00124 return;
00125 }
00126 var vector = new THREE.Vector3(mouse.x, mouse.y, 1);
00127 projector.unprojectVector(vector, camera);
00128 var raycaster = new THREE.Raycaster(camera.position, vector.sub(
00129 camera.position).normalize());
00130 var intersects = raycaster.intersectObjects(scene.children, true);
00131 if (intersects.length > 0) {
00132 var pick = null;
00133 for (var i = 0; i < intersects.length; ++i) {
00134 if ('emissive' in intersects[i].object.material) {
00135 pick = intersects[i];
00136 break;
00137 }
00138 }
00139 if (pick && INTERSECTED != pick.object) {
00140 if (INTERSECTED)
00141 INTERSECTED.material.emissive.setHex(INTERSECTED.currentHex);
00142 INTERSECTED = pick.object;
00143 INTERSECTED.currentHex = INTERSECTED.material.emissive.getHex();
00144 INTERSECTED.material.emissive.setHex(0x5f5f5f);
00145 renderer.render(scene, camera);
00146 if (JSROOT.gStyle.Tooltip)
00147 tooltip.show(INTERSECTED.name.length > 0 ? INTERSECTED.name
00148 : INTERSECTED.parent.name, 200);
00149 }
00150 } else {
00151 if (INTERSECTED) {
00152 INTERSECTED.material.emissive.setHex(INTERSECTED.currentHex);
00153 renderer.render(scene, camera);
00154 }
00155 INTERSECTED = null;
00156 if (JSROOT.gStyle.Tooltip)
00157 tooltip.hide();
00158 }
00159 }
00160 ;
00161
00162 $(renderer.domElement).on('touchstart mousedown', function(e) {
00163
00164 if (JSROOT.gStyle.Tooltip)
00165 tooltip.hide();
00166 e.preventDefault();
00167 var touch = e;
00168 if ('changedTouches' in e)
00169 touch = e.changedTouches[0];
00170 else if ('touches' in e)
00171 touch = e.touches[0];
00172 else if ('originalEvent' in e) {
00173 if ('changedTouches' in e.originalEvent)
00174 touch = e.originalEvent.changedTouches[0];
00175 else if ('touches' in e.originalEvent)
00176 touch = e.originalEvent.touches[0];
00177 }
00178 mouseX = touch.pageX;
00179 mouseY = touch.pageY;
00180 mouseDowned = true;
00181 });
00182 $(renderer.domElement).on('touchmove mousemove', function(e) {
00183 if (mouseDowned) {
00184 var touch = e;
00185 if ('changedTouches' in e)
00186 touch = e.changedTouches[0];
00187 else if ('touches' in e)
00188 touch = e.touches[0];
00189 else if ('originalEvent' in e) {
00190 if ('changedTouches' in e.originalEvent)
00191 touch = e.originalEvent.changedTouches[0];
00192 else if ('touches' in e.originalEvent)
00193 touch = e.originalEvent.touches[0];
00194 }
00195 var moveX = touch.pageX - mouseX;
00196 var moveY = touch.pageY - mouseY;
00197
00198 if ((moveY > 0 && toplevel.rotation.x < Math.PI * 3 / 4)
00199 || (moveY < 0 && toplevel.rotation.x > -Math.PI / 4)) {
00200 toplevel.rotation.x += moveY * 0.02;
00201 }
00202 toplevel.rotation.y += moveX * 0.02;
00203 renderer.render(scene, camera);
00204 mouseX = touch.pageX;
00205 mouseY = touch.pageY;
00206 } else {
00207 e.preventDefault();
00208 var mouse_x = 'offsetX' in e.originalEvent ? e.originalEvent.offsetX : e.originalEvent.layerX;
00209 var mouse_y = 'offsetY' in e.originalEvent ? e.originalEvent.offsetY : e.originalEvent.layerY;
00210 mouse.x = (mouse_x / renderer.domElement.width) * 2 - 1;
00211 mouse.y = -(mouse_y / renderer.domElement.height) * 2 + 1;
00212
00213 findIntersection();
00214 }
00215 });
00216 $(renderer.domElement).on('touchend mouseup', function(e) {
00217 mouseDowned = false;
00218 });
00219
00220 $(renderer.domElement).on('mousewheel', function(e, d) {
00221 e.preventDefault();
00222 camera.position.z += d * 20;
00223 renderer.render(scene, camera);
00224 });
00225
00226 $(renderer.domElement).on('contextmenu', function(e) {
00227
00228 e.preventDefault();
00229
00230 if (JSROOT.gStyle.Tooltip) tooltip.hide();
00231
00232 var menu = JSROOT.Painter.createmenu(e.originalEvent);
00233
00234 var item = JSROOT.gStyle.Tooltip ? "Disable tooltip" : "Enable tooltip";
00235
00236 JSROOT.Painter.menuitem(menu, item, function() {
00237 JSROOT.gStyle.Tooltip = !JSROOT.gStyle.Tooltip;
00238 tooltip.hide();
00239 });
00240
00241 if (painter)
00242 JSROOT.Painter.menuitem(menu, "Switch to 2D", function() {
00243 $(painter.svg_pad()).show().parent().find(renderer.domElement).remove();
00244 tooltip.hide();
00245 painter.Draw2D();
00246 });
00247 JSROOT.Painter.menuitem(menu, "Close", function() { });
00248
00249 });
00250 }
00251
00252 JSROOT.Painter.real_drawHistogram2D = function(painter) {
00253
00254 var w = Number(painter.svg_pad(true).attr("width")),
00255 h = Number(painter.svg_pad(true).attr("height")), size = 100;
00256
00257 var xmin = painter.xmin, xmax = painter.xmax;
00258 if (painter.zoom_xmin != painter.zoom_xmax) {
00259 xmin = painter.zoom_xmin;
00260 xmax = painter.zoom_xmax;
00261 }
00262 var ymin = painter.ymin, ymax = painter.ymax;
00263 if (painter.zoom_ymin != painter.zoom_ymax) {
00264 ymin = painter.zoom_ymin;
00265 ymax = painter.zoom_ymax;
00266 }
00267
00268 var tx, utx, ty, uty, tz, utz;
00269
00270 if (painter.options.Logx) {
00271 tx = d3.scale.log().domain([ xmin, xmax ]).range([ -size, size ]);
00272 utx = d3.scale.log().domain([ -size, size ]).range([ xmin, xmax ]);
00273 } else {
00274 tx = d3.scale.linear().domain([ xmin, xmax ]).range([ -size, size ]);
00275 utx = d3.scale.linear().domain([ -size, size ]).range([ xmin, xmax ]);
00276 }
00277 if (painter.options.Logy) {
00278 ty = d3.scale.log().domain([ ymin, ymax ]).range([ -size, size ]);
00279 uty = d3.scale.log().domain([ size, -size ]).range([ ymin, ymax ]);
00280 } else {
00281 ty = d3.scale.linear().domain([ ymin, ymax ]).range([ -size, size ]);
00282 uty = d3.scale.linear().domain([ size, -size ]).range([ ymin, ymax ]);
00283 }
00284 if (painter.options.Logz) {
00285 tz = d3.scale.log().domain([ painter.gminbin, Math.ceil(painter.gmaxbin / 100) * 105 ]).range([ 0, size * 2 ]);
00286 utz = d3.scale.log().domain([ 0, size * 2 ]).range([ painter.gminbin, Math.ceil(painter.gmaxbin / 100) * 105 ]);
00287 } else {
00288 tz = d3.scale.linear().domain([ painter.gminbin, Math.ceil(painter.gmaxbin / 100) * 105 ]).range( [ 0, size * 2 ]);
00289 utz = d3.scale.linear().domain([ 0, size * 2 ]).range( [ painter.gminbin, Math.ceil(painter.gmaxbin / 100) * 105 ]);
00290 }
00291
00292 var constx = (size * 2 / painter.nbinsx) / painter.gmaxbin;
00293 var consty = (size * 2 / painter.nbinsy) / painter.gmaxbin;
00294
00295 var colorFlag = (painter.options.Color > 0);
00296 var fcolor = d3.rgb(JSROOT.Painter.root_colors[painter.histo['fFillColor']]);
00297
00298 var local_bins = painter.CreateDrawBins(100, 100, 2, (JSROOT.gStyle.Tooltip ? 1 : 0));
00299
00300
00301 var scene = new THREE.Scene();
00302
00303 var toplevel = new THREE.Object3D();
00304 toplevel.rotation.x = 30 * Math.PI / 180;
00305 toplevel.rotation.y = 30 * Math.PI / 180;
00306 scene.add(toplevel);
00307
00308 var wireMaterial = new THREE.MeshBasicMaterial({
00309 color : 0x000000,
00310 wireframe : true,
00311 wireframeLinewidth : 0.5,
00312 side : THREE.DoubleSide
00313 });
00314
00315
00316 var cube = new THREE.Mesh(new THREE.BoxGeometry(size * 2, size * 2, size * 2), wireMaterial);
00317
00318
00319 var helper = new THREE.BoxHelper(cube);
00320 helper.material.color.set(0x000000);
00321
00322 var box = new THREE.Object3D();
00323 box.add(helper);
00324 box.position.y = size;
00325
00326
00327 toplevel.add(box);
00328
00329 var textMaterial = new THREE.MeshBasicMaterial({ color : 0x000000 });
00330
00331
00332 var geometry = new THREE.Geometry();
00333 var imax, istep, len = 3, plen, sin45 = Math.sin(45);
00334 var text3d, text;
00335 var xmajors = tx.ticks(8);
00336 var xminors = tx.ticks(50);
00337 for (var i = -size, j = 0, k = 0; i < size; ++i) {
00338 var is_major = (utx(i) <= xmajors[j] && utx(i + 1) > xmajors[j]) ? true : false;
00339 var is_minor = (utx(i) <= xminors[k] && utx(i + 1) > xminors[k]) ? true : false;
00340 plen = (is_major ? len + 2 : len) * sin45;
00341 if (is_major) {
00342 text3d = new THREE.TextGeometry(xmajors[j], { size : 7, height : 0, curveSegments : 10 });
00343 ++j;
00344
00345 text3d.computeBoundingBox();
00346 var centerOffset = 0.5 * (text3d.boundingBox.max.x - text3d.boundingBox.min.x);
00347
00348 text = new THREE.Mesh(text3d, textMaterial);
00349 text.position.set(i - centerOffset, -13, size + plen);
00350 toplevel.add(text);
00351
00352 text = new THREE.Mesh(text3d, textMaterial);
00353 text.position.set(i + centerOffset, -13, -size - plen);
00354 text.rotation.y = Math.PI;
00355 toplevel.add(text);
00356 }
00357 if (is_major || is_minor) {
00358 ++k;
00359 geometry.vertices.push(new THREE.Vector3(i, 0, size));
00360 geometry.vertices.push(new THREE.Vector3(i, -plen, size + plen));
00361 geometry.vertices.push(new THREE.Vector3(i, 0, -size));
00362 geometry.vertices.push(new THREE.Vector3(i, -plen, -size - plen));
00363 }
00364 }
00365 var ymajors = ty.ticks(8);
00366 var yminors = ty.ticks(50);
00367 for (var i = size, j = 0, k = 0; i > -size; --i) {
00368 var is_major = (uty(i) <= ymajors[j] && uty(i - 1) > ymajors[j]) ? true : false;
00369 var is_minor = (uty(i) <= yminors[k] && uty(i - 1) > yminors[k]) ? true : false;
00370 plen = (is_major ? len + 2 : len) * sin45;
00371 if (is_major) {
00372 text3d = new THREE.TextGeometry(ymajors[j], { size : 7, height : 0, curveSegments : 10 });
00373 ++j;
00374
00375 text3d.computeBoundingBox();
00376 var centerOffset = 0.5 * (text3d.boundingBox.max.x - text3d.boundingBox.min.x);
00377
00378 text = new THREE.Mesh(text3d, textMaterial);
00379 text.position.set(size + plen, -13, i + centerOffset);
00380 text.rotation.y = Math.PI / 2;
00381 toplevel.add(text);
00382
00383 text = new THREE.Mesh(text3d, textMaterial);
00384 text.position.set(-size - plen, -13, i - centerOffset);
00385 text.rotation.y = -Math.PI / 2;
00386 toplevel.add(text);
00387 }
00388 if (is_major || is_minor) {
00389 ++k;
00390 geometry.vertices.push(new THREE.Vector3(size, 0, i));
00391 geometry.vertices.push(new THREE.Vector3(size + plen, -plen, i));
00392 geometry.vertices.push(new THREE.Vector3(-size, 0, i));
00393 geometry.vertices.push(new THREE.Vector3(-size - plen, -plen, i));
00394 }
00395 }
00396 var zmajors = tz.ticks(8);
00397 var zminors = tz.ticks(50);
00398 for (var i = 0, j = 0, k = 0; i < (size * 2); ++i) {
00399 var is_major = (utz(i) <= zmajors[j] && utz(i + 1) > zmajors[j]) ? true : false;
00400 var is_minor = (utz(i) <= zminors[k] && utz(i + 1) > zminors[k]) ? true : false;
00401 plen = (is_major ? len + 2 : len) * sin45;
00402 if (is_major) {
00403 text3d = new THREE.TextGeometry(zmajors[j], { size : 7, height : 0, curveSegments : 10 });
00404 ++j;
00405
00406 text3d.computeBoundingBox();
00407 var offset = 0.8 * (text3d.boundingBox.max.x - text3d.boundingBox.min.x);
00408
00409 text = new THREE.Mesh(text3d, textMaterial);
00410 text.position.set(size + offset + 5, i - 2.5, size + offset + 5);
00411 text.rotation.y = Math.PI * 3 / 4;
00412 toplevel.add(text);
00413
00414 text = new THREE.Mesh(text3d, textMaterial);
00415 text.position.set(size + offset + 5, i - 2.5, -size - offset - 5);
00416 text.rotation.y = -Math.PI * 3 / 4;
00417 toplevel.add(text);
00418
00419 text = new THREE.Mesh(text3d, textMaterial);
00420 text.position.set(-size - offset - 5, i - 2.5, size + offset + 5);
00421 text.rotation.y = Math.PI / 4;
00422 toplevel.add(text);
00423
00424 text = new THREE.Mesh(text3d, textMaterial);
00425 text.position.set(-size - offset - 5, i - 2.5, -size - offset - 5);
00426 text.rotation.y = -Math.PI / 4;
00427 toplevel.add(text);
00428 }
00429 if (is_major || is_minor) {
00430 ++k;
00431 geometry.vertices.push(new THREE.Vector3(size, i, size));
00432 geometry.vertices.push(new THREE.Vector3(size + plen, i, size + plen));
00433 geometry.vertices.push(new THREE.Vector3(size, i, -size));
00434 geometry.vertices.push(new THREE.Vector3(size + plen, i, -size - plen));
00435 geometry.vertices.push(new THREE.Vector3(-size, i, size));
00436 geometry.vertices.push(new THREE.Vector3(-size - plen, i, size + plen));
00437 geometry.vertices.push(new THREE.Vector3(-size, i, -size));
00438 geometry.vertices.push(new THREE.Vector3(-size - plen, i, -size - plen));
00439 }
00440 }
00441
00442
00443 var lineMaterial = new THREE.LineBasicMaterial({ color : 0x000000 });
00444 var line = new THREE.Line(geometry, lineMaterial);
00445 line.type = THREE.LinePieces;
00446 toplevel.add(line);
00447
00448
00449
00450 var fillcolor = new THREE.Color(0xDDDDDD);
00451 fillcolor.setRGB(fcolor.r / 255, fcolor.g / 255, fcolor.b / 255);
00452 var bin, wei, hh;
00453
00454 for (var i = 0; i < local_bins.length; ++i) {
00455 hh = local_bins[i];
00456 wei = tz(hh.z);
00457
00458 bin = THREE.SceneUtils.createMultiMaterialObject(
00459 new THREE.BoxGeometry(2 * size / painter.nbinsx, wei, 2 * size / painter.nbinsy),
00460 [ new THREE.MeshLambertMaterial({ color : fillcolor.getHex(), shading : THREE.NoShading }), wireMaterial ]);
00461 bin.position.x = tx(hh.x);
00462 bin.position.y = wei / 2;
00463 bin.position.z = -(ty(hh.y));
00464
00465 if (JSROOT.gStyle.Tooltip)
00466 bin.name = hh.tip;
00467 toplevel.add(bin);
00468 }
00469
00470 delete local_bins;
00471 local_bins = null;
00472
00473
00474 var pointLight = new THREE.PointLight(0xcfcfcf);
00475 pointLight.position.set(0, 50, 250);
00476 scene.add(pointLight);
00477
00478
00479
00480
00481
00482
00483
00484 var camera = new THREE.PerspectiveCamera(45, w / h, 1, 1000);
00485 camera.position.set(0, size / 2, 500);
00486 camera.lookat = cube;
00487
00492 var Detector = {
00493 canvas : !!window.CanvasRenderingContext2D,
00494 webgl : (function() { try {
00495 return !!window.WebGLRenderingContext && !!document.createElement('canvas').getContext('experimental-webgl');
00496 } catch (e) {
00497 return false;
00498 }
00499 })(),
00500 workers : !!window.Worker,
00501 fileapi : window.File && window.FileReader && window.FileList && window.Blob
00502 };
00503
00504 var renderer = Detector.webgl ? new THREE.WebGLRenderer({ antialias : true }) :
00505 new THREE.CanvasRenderer({ antialias : true });
00506 renderer.setClearColor(0xffffff, 1);
00507 renderer.setSize(w, h);
00508 $(painter.svg_pad()).hide().parent().append(renderer.domElement);
00509 renderer.render(scene, camera);
00510
00511 JSROOT.Painter.add3DInteraction(renderer, scene, camera, toplevel, painter);
00512 }
00513
00514 JSROOT.Painter.real_drawHistogram3D = function(divid, histo, opt) {
00515
00516 var logx = false, logy = false, logz = false, gridx = false, gridy = false, gridz = false;
00517
00518 var painter = new JSROOT.TObjectPainter();
00519 painter.SetDivId(divid, -1);
00520 var pad = painter.root_pad();
00521
00522 var render_to;
00523 if (painter.svg_pad())
00524 render_to = $(painter.svg_pad()).hide().parent();
00525 else
00526 render_to = $("#" + divid);
00527
00528 var opt = histo['fOption'].toLowerCase();
00529
00530
00531 if (pad) {
00532 logx = pad['fLogx'];
00533 logy = pad['fLogy'];
00534 logz = pad['fLogz'];
00535 gridx = pad['fGridx'];
00536 gridy = pad['fGridy'];
00537 gridz = pad['fGridz'];
00538 }
00539
00540 var fillcolor = JSROOT.Painter.root_colors[histo['fFillColor']];
00541 var linecolor = JSROOT.Painter.root_colors[histo['fLineColor']];
00542 if (histo['fFillColor'] == 0) {
00543 fillcolor = '#4572A7';
00544 }
00545 if (histo['fLineColor'] == 0) {
00546 linecolor = '#4572A7';
00547 }
00548 var nbinsx = histo['fXaxis']['fNbins'];
00549 var nbinsy = histo['fYaxis']['fNbins'];
00550 var nbinsz = histo['fZaxis']['fNbins'];
00551 var scalex = (histo['fXaxis']['fXmax'] - histo['fXaxis']['fXmin']) / histo['fXaxis']['fNbins'];
00552 var scaley = (histo['fYaxis']['fXmax'] - histo['fYaxis']['fXmin']) / histo['fYaxis']['fNbins'];
00553 var scalez = (histo['fZaxis']['fXmax'] - histo['fZaxis']['fXmin']) / histo['fZaxis']['fNbins'];
00554 var maxbin = -1e32, minbin = 1e32;
00555 maxbin = d3.max(histo['fArray']);
00556 minbin = d3.min(histo['fArray']);
00557 var bins = new Array();
00558 for (var i = 0; i <= nbinsx + 2; ++i) {
00559 for (var j = 0; j < nbinsy + 2; ++j) {
00560 for (var k = 0; k < nbinsz + 2; ++k) {
00561 var bin_content = histo.getBinContent(i, j, k);
00562 if (bin_content > minbin) {
00563 var point = {
00564 x : histo['fXaxis']['fXmin'] + (i * scalex),
00565 y : histo['fYaxis']['fXmin'] + (j * scaley),
00566 z : histo['fZaxis']['fXmin'] + (k * scalez),
00567 n : bin_content
00568 };
00569 bins.push(point);
00570 }
00571 }
00572 }
00573 }
00574 var w = render_to.width(), h = render_to.height(), size = 100;
00575 if (h<10) { render_to.height(0.66*w); h = render_to.height(); }
00576
00577 if (logx) {
00578 var tx = d3.scale.log().domain([ histo['fXaxis']['fXmin'], histo['fXaxis']['fXmax'] ]).range( [ -size, size ]);
00579 var utx = d3.scale.log().domain([ -size, size ]).range([ histo['fXaxis']['fXmin'], histo['fXaxis']['fXmax'] ]);
00580 } else {
00581 var tx = d3.scale.linear().domain( [ histo['fXaxis']['fXmin'], histo['fXaxis']['fXmax'] ]).range( [ -size, size ]);
00582 var utx = d3.scale.linear().domain([ -size, size ]).range([ histo['fXaxis']['fXmin'], histo['fXaxis']['fXmax'] ]);
00583 }
00584 if (logy) {
00585 var ty = d3.scale.log().domain([ histo['fYaxis']['fXmin'], histo['fYaxis']['fXmax'] ]).range( [ -size, size ]);
00586 var uty = d3.scale.log().domain([ size, -size ]).range([ histo['fYaxis']['fXmin'], histo['fYaxis']['fXmax'] ]);
00587 } else {
00588 var ty = d3.scale.linear().domain( [ histo['fYaxis']['fXmin'], histo['fYaxis']['fXmax'] ]).range([ -size, size ]);
00589 var uty = d3.scale.linear().domain([ size, -size ]).range([ histo['fYaxis']['fXmin'], histo['fYaxis']['fXmax'] ]);
00590 }
00591 if (logz) {
00592 var tz = d3.scale.log().domain([ histo['fZaxis']['fXmin'], histo['fZaxis']['fXmax'] ]).range([ -size, size ]);
00593 var utz = d3.scale.log().domain([ -size, size ]).range([ histo['fZaxis']['fXmin'], histo['fZaxis']['fXmax'] ]);
00594 } else {
00595 var tz = d3.scale.linear().domain([ histo['fZaxis']['fXmin'], histo['fZaxis']['fXmax'] ]).range([ -size, size ]);
00596 var utz = d3.scale.linear().domain([ -size, size ]).range([ histo['fZaxis']['fXmin'], histo['fZaxis']['fXmax'] ]);
00597 }
00598
00599
00600 var scene = new THREE.Scene();
00601
00602 var toplevel = new THREE.Object3D();
00603 toplevel.rotation.x = 30 * Math.PI / 180;
00604 toplevel.rotation.y = 30 * Math.PI / 180;
00605 scene.add(toplevel);
00606
00607 var wireMaterial = new THREE.MeshBasicMaterial({
00608 color : 0x000000,
00609 wireframe : true,
00610 wireframeLinewidth : 0.5,
00611 side : THREE.DoubleSide
00612 });
00613
00614
00615 var cube = new THREE.Mesh(new THREE.BoxGeometry(size * 2, size * 2, size * 2), wireMaterial);
00616
00617 var helper = new THREE.BoxHelper(cube);
00618 helper.material.color.set(0x000000);
00619
00620
00621 toplevel.add(helper);
00622
00623 var textMaterial = new THREE.MeshBasicMaterial({ color : 0x000000 });
00624
00625
00626 var geometry = new THREE.Geometry();
00627 var imax, istep, len = 3, plen, sin45 = Math.sin(45);
00628 var text3d, text;
00629 var xmajors = tx.ticks(5);
00630 var xminors = tx.ticks(25);
00631 for (var i = -size, j = 0, k = 0; i <= size; ++i) {
00632 var is_major = (utx(i) <= xmajors[j] && utx(i + 1) > xmajors[j]) ? true : false;
00633 var is_minor = (utx(i) <= xminors[k] && utx(i + 1) > xminors[k]) ? true : false;
00634 plen = (is_major ? len + 2 : len) * sin45;
00635 if (is_major) {
00636 text3d = new THREE.TextGeometry(xmajors[j], { size : 7, height : 0, curveSegments : 10 });
00637 ++j;
00638
00639 text3d.computeBoundingBox();
00640 var centerOffset = 0.5 * (text3d.boundingBox.max.x - text3d.boundingBox.min.x);
00641
00642 text = new THREE.Mesh(text3d, textMaterial);
00643 text.position.set(i - centerOffset, -size - 13, size + plen);
00644 toplevel.add(text);
00645
00646 text = new THREE.Mesh(text3d, textMaterial);
00647 text.position.set(i + centerOffset, -size - 13, -size - plen);
00648 text.rotation.y = Math.PI;
00649 toplevel.add(text);
00650 }
00651 if (is_major || is_minor) {
00652 ++k;
00653 geometry.vertices.push(new THREE.Vector3(i, -size, size));
00654 geometry.vertices.push(new THREE.Vector3(i, -size - plen, size + plen));
00655 geometry.vertices.push(new THREE.Vector3(i, -size, -size));
00656 geometry.vertices.push(new THREE.Vector3(i, -size - plen, -size - plen));
00657 }
00658 }
00659 var ymajors = ty.ticks(5);
00660 var yminors = ty.ticks(25);
00661 for (var i = size, j = 0, k = 0; i > -size; --i) {
00662 var is_major = (uty(i) <= ymajors[j] && uty(i - 1) > ymajors[j]) ? true : false;
00663 var is_minor = (uty(i) <= yminors[k] && uty(i - 1) > yminors[k]) ? true : false;
00664 plen = (is_major ? len + 2 : len) * sin45;
00665 if (is_major) {
00666 text3d = new THREE.TextGeometry(ymajors[j], { size : 7, height : 0, curveSegments : 10 });
00667 ++j;
00668
00669 text3d.computeBoundingBox();
00670 var centerOffset = 0.5 * (text3d.boundingBox.max.x - text3d.boundingBox.min.x);
00671
00672 text = new THREE.Mesh(text3d, textMaterial);
00673 text.position.set(size + plen, -size - 13, i + centerOffset);
00674 text.rotation.y = Math.PI / 2;
00675 toplevel.add(text);
00676
00677 text = new THREE.Mesh(text3d, textMaterial);
00678 text.position.set(-size - plen, -size - 13, i - centerOffset);
00679 text.rotation.y = -Math.PI / 2;
00680 toplevel.add(text);
00681 }
00682 if (is_major || is_minor) {
00683 ++k;
00684 geometry.vertices.push(new THREE.Vector3(size, -size, i));
00685 geometry.vertices.push(new THREE.Vector3(size + plen, -size - plen, i));
00686 geometry.vertices.push(new THREE.Vector3(-size, -size, i));
00687 geometry.vertices.push(new THREE.Vector3(-size - plen, -size - plen, i));
00688 }
00689 }
00690 var zmajors = tz.ticks(5);
00691 var zminors = tz.ticks(25);
00692 for (var i = -size, j = 0, k = 0; i <= size; ++i) {
00693 var is_major = (utz(i) <= zmajors[j] && utz(i + 1) > zmajors[j]) ? true : false;
00694 var is_minor = (utz(i) <= zminors[k] && utz(i + 1) > zminors[k]) ? true : false;
00695 plen = (is_major ? len + 2 : len) * sin45;
00696 if (is_major) {
00697 text3d = new THREE.TextGeometry(zmajors[j], { size : 7, height : 0, curveSegments : 10 });
00698 ++j;
00699
00700 text3d.computeBoundingBox();
00701 var offset = 0.6 * (text3d.boundingBox.max.x - text3d.boundingBox.min.x);
00702
00703 text = new THREE.Mesh(text3d, textMaterial);
00704 text.position.set(size + offset + 7, i - 2.5, size + offset + 7);
00705 text.rotation.y = Math.PI * 3 / 4;
00706 toplevel.add(text);
00707
00708 text = new THREE.Mesh(text3d, textMaterial);
00709 text.position.set(size + offset + 7, i - 2.5, -size - offset - 7);
00710 text.rotation.y = -Math.PI * 3 / 4;
00711 toplevel.add(text);
00712
00713 text = new THREE.Mesh(text3d, textMaterial);
00714 text.position.set(-size - offset - 7, i - 2.5, size + offset + 7);
00715 text.rotation.y = Math.PI / 4;
00716 toplevel.add(text);
00717
00718 text = new THREE.Mesh(text3d, textMaterial);
00719 text.position.set(-size - offset - 7, i - 2.5, -size - offset - 7);
00720 text.rotation.y = -Math.PI / 4;
00721 toplevel.add(text);
00722 }
00723 if (is_major || is_minor) {
00724 ++k;
00725 geometry.vertices.push(new THREE.Vector3(size, i, size));
00726 geometry.vertices.push(new THREE.Vector3(size + plen, i, size + plen));
00727 geometry.vertices.push(new THREE.Vector3(size, i, -size));
00728 geometry.vertices.push(new THREE.Vector3(size + plen, i, -size - plen));
00729 geometry.vertices.push(new THREE.Vector3(-size, i, size));
00730 geometry.vertices.push(new THREE.Vector3(-size - plen, i, size + plen));
00731 geometry.vertices.push(new THREE.Vector3(-size, i, -size));
00732 geometry.vertices.push(new THREE.Vector3(-size - plen, i, -size - plen));
00733 }
00734 }
00735
00736
00737 var lineMaterial = new THREE.LineBasicMaterial({ color : 0x000000 });
00738 var line = new THREE.Line(geometry, lineMaterial);
00739 line.type = THREE.LinePieces;
00740 toplevel.add(line);
00741
00742
00743 var constx = (size * 2 / histo['fXaxis']['fNbins']) / maxbin;
00744 var consty = (size * 2 / histo['fYaxis']['fNbins']) / maxbin;
00745 var constz = (size * 2 / histo['fZaxis']['fNbins']) / maxbin;
00746
00747 var optFlag = (opt.indexOf('colz') != -1 || opt.indexOf('col') != -1);
00748 var fcolor = d3.rgb(JSROOT.Painter.root_colors[histo['fFillColor']]);
00749 var fillcolor = new THREE.Color(0xDDDDDD);
00750 fillcolor.setRGB(fcolor.r / 255, fcolor.g / 255, fcolor.b / 255);
00751 var bin, wei;
00752 for (var i = 0; i < bins.length; ++i) {
00753 wei = (optFlag ? maxbin : bins[i].n);
00754 if (opt.indexOf('box1') != -1) {
00755 bin = new THREE.Mesh(new THREE.SphereGeometry(0.5 * wei * constx ),
00756 new THREE.MeshPhongMaterial({ color : fillcolor.getHex(), specular : 0xbfbfbf}));
00757 } else {
00758 bin = THREE.SceneUtils.createMultiMaterialObject(
00759 new THREE.BoxGeometry(wei * constx, wei * constz, wei * consty),
00760 [ new THREE.MeshLambertMaterial({ color : fillcolor.getHex(), shading : THREE.NoShading }), wireMaterial ]);
00761 }
00762 bin.position.x = tx(bins[i].x - (scalex / 2));
00763 bin.position.y = tz(bins[i].z - (scalez / 2));
00764 bin.position.z = -(ty(bins[i].y - (scaley / 2)));
00765 bin.name = "x: [" + bins[i].x.toPrecision(4) + ", "
00766 + (bins[i].x + scalex).toPrecision(4) + "]<br/>"
00767 + "y: [" + bins[i].y.toPrecision(4) + ", "
00768 + (bins[i].y + scaley).toPrecision(4) + "]<br/>"
00769 + "z: [" + bins[i].z.toPrecision(4) + ", "
00770 + (bins[i].z + scalez).toPrecision(4) + "]<br/>"
00771 + "entries: " + bins[i].n.toFixed();
00772 toplevel.add(bin);
00773 }
00774
00775 var pointLight = new THREE.PointLight(0xcfcfcf);
00776 pointLight.position.set(0, 50, 250);
00777 scene.add(pointLight);
00778
00779
00780
00781
00782
00783 var camera = new THREE.PerspectiveCamera(45, w / h, 1, 1000);
00784 camera.position.set(0, 0, 500);
00785 camera.lookat = cube;
00786
00791 var Detector = {
00792 canvas : !!window.CanvasRenderingContext2D,
00793 webgl : (function() {
00794 try {
00795 return !!window.WebGLRenderingContext
00796 && !!document.createElement('canvas')
00797 .getContext('experimental-webgl');
00798 } catch (e) {
00799 return false;
00800 }
00801 })(),
00802 workers : !!window.Worker,
00803 fileapi : window.File && window.FileReader
00804 && window.FileList && window.Blob
00805 };
00806
00807 var renderer = Detector.webgl ?
00808 new THREE.WebGLRenderer({ antialias : true }) :
00809 new THREE.CanvasRenderer({antialias : true });
00810 renderer.setClearColor(0xffffff, 1);
00811 renderer.setSize(w, h);
00812 render_to.append(renderer.domElement);
00813 renderer.render(scene, camera);
00814
00815 JSROOT.Painter.add3DInteraction(renderer, scene, camera, toplevel, null);
00816 }
00817
00818 })();
00819