Module format back to commonjs. Major JSROOT update

This commit is contained in:
Alexander Nozik 2019-04-05 14:47:00 +03:00
parent 9f80e0894b
commit 2de0404a03
9 changed files with 6515 additions and 5810 deletions

View File

@ -106,7 +106,7 @@ subprojects {
metaInfo = true metaInfo = true
sourceMap = true sourceMap = true
sourceMapEmbedSources = "always" sourceMapEmbedSources = "always"
moduleKind = "umd" moduleKind = "commonjs"
} }
} }
} }

View File

@ -1,4 +1,4 @@
@file:JsModule("JSRootCore.js") @file:JsModule("JSRootUtils")
@file:JsNonModule @file:JsNonModule
package hep.dataforge.vis.spatial.jsroot package hep.dataforge.vis.spatial.jsroot

View File

@ -19,8 +19,6 @@ class JSRootDemoApp : ApplicationBase() {
override val stateKeys: List<String> = emptyList() override val stateKeys: List<String> = emptyList()
override fun start(state: Map<String, Any>) { override fun start(state: Map<String, Any>) {
// require("JSRootGeoBase.js")
// require("JSRootCore.js")
//TODO remove after DI fix //TODO remove after DI fix

View File

@ -1,4 +1,4 @@
@file:JsModule("JSRootGeoBase.js") @file:JsModule("JSRootGeoBase")
@file:JsNonModule @file:JsNonModule
package hep.dataforge.vis.spatial.jsroot package hep.dataforge.vis.spatial.jsroot

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,761 @@
/** Generate mask for given bit
*
* @param {number} n bit number
* @returns {Number} produced make
* @private */
export function BIT(n) {
return 1 << (n);
}
/** Wrapper for console.log, let redirect output to specified div element
* @private */
function console(value, divid) {
if ((typeof divid == 'string') && document.getElementById(divid))
document.getElementById(divid).innerHTML = value;
else if ((typeof console != 'undefined') && (typeof console.log == 'function'))
console.log(value);
}
/** @summary Wrapper for alert, throws Error in Node.js
* @private */
export function alert(msg) {
if (this.nodeis) throw new Error(msg);
if (typeof alert === 'function') alert(msg);
else console('ALERT: ' + msg);
}
/**
* @summary Seed simple random generator
*
* @private
* @param {number} i seed value
*/
export function seed(i) {
i = Math.abs(i);
if (i > 1e8) i = Math.abs(1e8 * Math.sin(i)); else if (i < 1) i *= 1e8;
this.m_w = Math.round(i);
this.m_z = 987654321;
}
/**
* @summary Simple random generator
*
* @desc Works like Math.random(), but with configurable seed - see {@link JSROOT.seed}
* @private
* @returns {number} random value between 0 (inclusive) and 1.0 (exclusive)
*/
export function random() {
if (this.m_z === undefined) return Math.random();
this.m_z = (36969 * (this.m_z & 65535) + (this.m_z >> 16)) & 0xffffffff;
this.m_w = (18000 * (this.m_w & 65535) + (this.m_w >> 16)) & 0xffffffff;
var result = ((this.m_z << 16) + this.m_w) & 0xffffffff;
result /= 4294967296;
return result + 0.5;
}
/** @summary Should be used to reintroduce objects references, produced by TBufferJSON.
*
* @desc Replace all references inside object, object should not be null
* Idea of the code taken from JSON-R code, found on
* https://github.com/graniteds/jsonr
* Only unref part was used, arrays are not accounted as objects
* @param {object} obj object where references will be replaced
* @returns {object} same object with replaced references
* @private */
function JSONR_unref(obj) {
var map = [], newfmt = undefined;
function unref_value(value) {
if ((value === null) || (value === undefined)) return;
if (typeof value === 'string') {
if (newfmt || (value.length < 6) || (value.indexOf("$ref:") !== 0)) return;
let ref = parseInt(value.substr(5));
if (isNaN(ref) || (ref < 0) || (ref >= map.length)) return;
newfmt = false;
return map[ref];
}
if (typeof value !== 'object') return;
var i, k, res, proto = Object.prototype.toString.apply(value);
// scan array - it can contain other objects
if ((proto.indexOf('[object') === 0) && (proto.indexOf('Array]') > 0)) {
for (i = 0; i < value.length; ++i) {
res = unref_value(value[i]);
if (res !== undefined) value[i] = res;
}
return;
}
var ks = Object.keys(value), len = ks.length;
if ((newfmt !== false) && (len === 1) && (ks[0] === '$ref')) {
var ref = parseInt(value['$ref']);
if (isNaN(ref) || (ref < 0) || (ref >= map.length)) return;
newfmt = true;
return map[ref];
}
if ((newfmt !== false) && (len > 1) && (ks[0] === '$arr') && (ks[1] === 'len')) {
// this is ROOT-coded array
var arr = null, dflt = (value.$arr === "Bool") ? false : 0;
switch (value.$arr) {
case "Int8" :
arr = new Int8Array(value.len);
break;
case "Uint8" :
arr = new Uint8Array(value.len);
break;
case "Int16" :
arr = new Int16Array(value.len);
break;
case "Uint16" :
arr = new Uint16Array(value.len);
break;
case "Int32" :
arr = new Int32Array(value.len);
break;
case "Uint32" :
arr = new Uint32Array(value.len);
break;
case "Float32" :
arr = new Float32Array(value.len);
break;
case "Int64" :
case "Uint64" :
case "Float64" :
arr = new Float64Array(value.len);
break;
default :
arr = new Array(value.len);
break;
}
for (var k = 0; k < value.len; ++k) arr[k] = dflt;
var nkey = 2, p = 0;
while (nkey < len) {
if (ks[nkey][0] === "p") p = value[ks[nkey++]]; // position
if (ks[nkey][0] !== 'v') throw new Error('Unexpected member ' + ks[nkey] + ' in array decoding');
var v = value[ks[nkey++]]; // value
if (typeof v === 'object') {
for (var k = 0; k < v.length; ++k) arr[p++] = v[k];
} else {
arr[p++] = v;
if ((nkey < len) && (ks[nkey][0] === 'n')) {
var cnt = value[ks[nkey++]]; // counter
while (--cnt) arr[p++] = v;
}
}
}
return arr;
}
if ((newfmt !== false) && (len === 3) && (ks[0] === '$pair') && (ks[1] === 'first') && (ks[2] === 'second')) {
newfmt = true;
var f1 = unref_value(value.first),
s1 = unref_value(value.second);
if (f1 !== undefined) value.first = f1;
if (s1 !== undefined) value.second = s1;
value._typename = value['$pair'];
delete value['$pair'];
return; // pair object is not counted in the objects map
}
// debug code, can be commented out later
if (map.indexOf(value) >= 0) {
console('should never happen - object already in the map');
return;
}
// add object to object map
map.push(value);
// add methods to all objects, where _typename is specified
//if ('_typename' in value) JSROOT.addMethods(value);
for (k = 0; k < len; ++k) {
i = ks[k];
res = unref_value(value[i]);
if (res !== undefined) value[i] = res;
}
}
unref_value(obj);
return obj;
}
/** @summary Just copies (not clone) all fields from source to the target object
* @desc This is simple replacement of jQuery.extend method
* @private */
function extend(tgt, src) {
if ((src === null) || (typeof src !== 'object')) return tgt;
if ((tgt === null) || (typeof tgt !== 'object')) tgt = {};
for (var k in src)
tgt[k] = src[k];
return tgt;
}
/**
* @summary Parse JSON code produced with TBufferJSON.
*
* @param {string} json string to parse
* @return {object|null} returns parsed object
*/
export function parse(json) {
if (!json) return null;
let obj = JSON.parse(json);
if (obj) obj = JSONR_unref(obj);
return obj;
}
/**
* @summary Parse multi.json request results
* @desc Method should be used to parse JSON code, produced by multi.json request of THttpServer
*
* @param {string} json string to parse
* @return {Array|null} returns array of parsed elements
*/
export function parse_multi(json) {
if (!json) return null;
let arr = JSON.parse(json);
if (arr && arr.length)
for (let i = 0; i < arr.length; ++i)
arr[i] = JSONR_unref(arr[i]);
return arr;
}
/**
* @summary Method converts JavaScript object into ROOT-like JSON
*
* @desc Produced JSON can be used in JSROOT.parse() again
* When performed properly, JSON can be used in TBufferJSON to read data back with C++
*/
export function toJSON(obj) {
if (!obj || typeof obj !== 'object') return "";
var map = []; // map of stored objects
function copy_value(value) {
if (typeof value === "function") return undefined;
if ((value === undefined) || (value === null) || (typeof value !== 'object')) return value;
var proto = Object.prototype.toString.apply(value);
// typed array need to be converted into normal array, otherwise looks strange
if ((proto.indexOf('[object ') === 0) && (proto.indexOf('Array]') === proto.length - 6)) {
var arr = new Array(value.length);
for (var i = 0; i < value.length; ++i)
arr[i] = copy_value(value[i]);
return arr;
}
// this is how reference is code
var refid = map.indexOf(value);
if (refid >= 0) return {$ref: refid};
var ks = Object.keys(value), len = ks.length, tgt = {};
if ((len === 3) && (ks[0] === '$pair') && (ks[1] === 'first') && (ks[2] === 'second')) {
// special handling of pair objects which does not included into objects map
tgt.$pair = value.$pair;
tgt.first = copy_value(value.first);
tgt.second = copy_value(value.second);
return tgt;
}
map.push(value);
for (var k = 0; k < len; ++k) {
var name = ks[k];
tgt[name] = copy_value(value[name]);
}
return tgt;
}
var tgt = copy_value(obj);
return JSON.stringify(tgt);
}
/**
* @summary Parse string value as array.
*
* @desc It could be just simple string: "value" or
* array with or without string quotes: [element], ['elem1',elem2]
*
* @private
*/
function ParseAsArray(val) {
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 split ourself, checking quotes and brackets
var nbr = 0, nquotes = 0, ndouble = 0, last = 1;
for (var indx = 1; indx < val.length; ++indx) {
if (nquotes > 0) {
if (val[indx] === "'") nquotes--;
continue;
}
if (ndouble > 0) {
if (val[indx] === '"') ndouble--;
continue;
}
switch (val[indx]) {
case "'":
nquotes++;
break;
case '"':
ndouble++;
break;
case "[":
nbr++;
break;
case "]":
if (indx < val.length - 1) {
nbr--;
break;
}
case ",":
if (nbr === 0) {
var sub = val.substring(last, indx).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);
last = indx + 1;
}
break;
}
}
if (res.length === 0)
res.push(val.substr(1, val.length - 2).trim());
return res;
}
/**
* @summary Find function with given name.
*
* @desc Function name may include several namespaces like 'JSROOT.Painter.drawFrame'
*
* @private
*/
function findFunction(name) {
if (typeof name === 'function') return name;
if (typeof name !== 'string') return null;
var names = name.split('.'), elem = null;
if (typeof window === 'object') elem = window;
if (names[0] === 'JSROOT') {
elem = this;
names.shift();
}
for (var n = 0; elem && (n < names.length); ++n)
elem = elem[names[n]];
return (typeof elem == 'function') ? elem : null;
}
/**
* @summary Generic method to invoke callback function.
*
* @param {object|function} func either normal function or container like
* { obj: object_pointer, func: name of method to call }
* @param arg1 first optional argument of callback
* @param arg2 second optional argument of callback
*
* @private
*/
function callBack(func, arg1, arg2) {
if (typeof func == 'string') func = findFunction(func);
if (!func) return;
if (typeof func == 'function') return func(arg1, arg2);
if (typeof func != 'object') return;
if (('obj' in func) && ('func' in func) &&
(typeof func.obj == 'object') && (typeof func.func == 'string') &&
(typeof func.obj[func.func] == 'function')) {
return func.obj[func.func](arg1, arg2);
}
}
let methodsCache = {}; // variable used to keep methods for known classes
/** @summary Returns methods for given typename
* @private
*/
function getMethods(typename, obj) {
var m = methodsCache[typename],
has_methods = (m !== undefined);
if (!has_methods) m = {};
// Due to binary I/O such TObject methods may not be set for derived classes
// Therefore when methods requested for given object, check also that basic methods are there
if ((typename === "TObject") || (typename === "TNamed") || (obj && (obj.fBits !== undefined)))
if (m.TestBit === undefined) {
m.TestBit = function (f) {
return (this.fBits & f) !== 0;
};
m.InvertBit = function (f) {
this.fBits = this.fBits ^ (f & 0xffffff);
};
}
if (has_methods) return m;
if ((typename === 'TList') || (typename === 'THashList')) {
m.Clear = function () {
this.arr = [];
this.opt = [];
};
m.Add = function (obj, opt) {
this.arr.push(obj);
this.opt.push((opt && typeof opt == 'string') ? opt : "");
};
m.AddFirst = function (obj, opt) {
this.arr.unshift(obj);
this.opt.unshift((opt && typeof opt == 'string') ? opt : "");
};
m.RemoveAt = function (indx) {
this.arr.splice(indx, 1);
this.opt.splice(indx, 1);
}
}
// if ((typename === "TPaveText") || (typename === "TPaveStats")) {
// m.AddText = function (txt) {
// // this.fLines.Add({ _typename: 'TLatex', fTitle: txt, fTextColor: 1 });
// var line = JSROOT.Create("TLatex");
// line.fTitle = txt;
// this.fLines.Add(line);
// };
// m.Clear = function () {
// this.fLines.Clear();
// }
// }
//
// if ((typename.indexOf("TF1") === 0) || (typename === "TF2")) {
// m.addFormula = function (obj) {
// if (!obj) return;
// if (this.formulas === undefined) this.formulas = [];
// this.formulas.push(obj);
// };
//
// m.evalPar = function (x, y) {
// if (!('_func' in this) || (this._title !== this.fTitle)) {
//
// var _func = this.fTitle, isformula = false, pprefix = "[";
// if (_func === "gaus") _func = "gaus(0)";
// if (this.fFormula && typeof this.fFormula.fFormula == "string") {
// if (this.fFormula.fFormula.indexOf("[](double*x,double*p)") === 0) {
// isformula = true;
// pprefix = "p[";
// _func = this.fFormula.fFormula.substr(21);
// } else {
// _func = this.fFormula.fFormula;
// pprefix = "[p";
// }
// if (this.fFormula.fClingParameters && this.fFormula.fParams) {
// for (var i = 0; i < this.fFormula.fParams.length; ++i) {
// var regex = new RegExp('(\\[' + this.fFormula.fParams[i].first + '\\])', 'g'),
// parvalue = this.fFormula.fClingParameters[this.fFormula.fParams[i].second];
// _func = _func.replace(regex, (parvalue < 0) ? "(" + parvalue + ")" : parvalue);
// }
// }
// }
//
// if ('formulas' in this)
// for (var i = 0; i < this.formulas.length; ++i)
// while (_func.indexOf(this.formulas[i].fName) >= 0)
// _func = _func.replace(this.formulas[i].fName, this.formulas[i].fTitle);
// _func = _func.replace(/\b(abs)\b/g, 'TMath::Abs')
// .replace(/TMath::Exp\(/g, 'Math.exp(')
// .replace(/TMath::Abs\(/g, 'Math.abs(');
// if (typeof JSROOT.Math == 'object') {
// this._math = JSROOT.Math;
// _func = _func.replace(/TMath::Prob\(/g, 'this._math.Prob(')
// .replace(/TMath::Gaus\(/g, 'this._math.Gaus(')
// .replace(/TMath::BreitWigner\(/g, 'this._math.BreitWigner(')
// .replace(/xygaus\(/g, 'this._math.gausxy(this, x, y, ')
// .replace(/gaus\(/g, 'this._math.gaus(this, x, ')
// .replace(/gausn\(/g, 'this._math.gausn(this, x, ')
// .replace(/expo\(/g, 'this._math.expo(this, x, ')
// .replace(/landau\(/g, 'this._math.landau(this, x, ')
// .replace(/landaun\(/g, 'this._math.landaun(this, x, ')
// .replace(/ROOT::Math::/g, 'this._math.');
// }
// for (var i = 0; i < this.fNpar; ++i) {
// var parname = pprefix + i + "]";
// while (_func.indexOf(parname) !== -1)
// _func = _func.replace(parname, '(' + this.GetParValue(i) + ')');
// }
// _func = _func.replace(/\b(sin)\b/gi, 'Math.sin')
// .replace(/\b(cos)\b/gi, 'Math.cos')
// .replace(/\b(tan)\b/gi, 'Math.tan')
// .replace(/\b(exp)\b/gi, 'Math.exp')
// .replace(/\b(pow)\b/gi, 'Math.pow')
// .replace(/pi/g, 'Math.PI');
// for (var n = 2; n < 10; ++n)
// _func = _func.replace('x^' + n, 'Math.pow(x,' + n + ')');
//
// if (isformula) {
// _func = _func.replace(/x\[0\]/g, "x");
// if (this._typename === "TF2") {
// _func = _func.replace(/x\[1\]/g, "y");
// this._func = new Function("x", "y", _func).bind(this);
// } else {
// this._func = new Function("x", _func).bind(this);
// }
// } else if (this._typename === "TF2")
// this._func = new Function("x", "y", "return " + _func).bind(this);
// else
// this._func = new Function("x", "return " + _func).bind(this);
//
// this._title = this.fTitle;
// }
//
// return this._func(x, y);
// };
// m.GetParName = function (n) {
// if (this.fFormula && this.fFormula.fParams) return this.fFormula.fParams[n].first;
// if (this.fNames && this.fNames[n]) return this.fNames[n];
// return "p" + n;
// };
// m.GetParValue = function (n) {
// if (this.fFormula && this.fFormula.fClingParameters) return this.fFormula.fClingParameters[n];
// if (this.fParams) return this.fParams[n];
// return undefined;
// };
// m.GetParError = function (n) {
// return this.fParErrors ? this.fParErrors[n] : undefined;
// };
// m.GetNumPars = function () {
// return this.fNpar;
// }
// }
if (((typename.indexOf("TGraph") === 0) || (typename === "TCutG")) && (typename !== "TGraphPolargram") && (typename !== "TGraphTime")) {
// check if point inside figure specified by the TGraph
m.IsInside = function (xp, yp) {
var i, j = this.fNpoints - 1, x = this.fX, y = this.fY, oddNodes = false;
for (i = 0; i < this.fNpoints; ++i) {
if ((y[i] < yp && y[j] >= yp) || (y[j] < yp && y[i] >= yp)) {
if (x[i] + (yp - y[i]) / (y[j] - y[i]) * (x[j] - x[i]) < xp) {
oddNodes = !oddNodes;
}
}
j = i;
}
return oddNodes;
};
}
if (typename.indexOf("TH1") === 0 ||
typename.indexOf("TH2") === 0 ||
typename.indexOf("TH3") === 0) {
m.getBinError = function (bin) {
// -*-*-*-*-*Return value of error associated to bin number bin*-*-*-*-*
// if the sum of squares of weights has been defined (via Sumw2),
// this function returns the sqrt(sum of w2).
// otherwise it returns the sqrt(contents) for this bin.
if (bin >= 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 trivial case, without expansion
this.fEntries++;
this.fTsumw = 0;
if ((bin >= 0) && (bin < this.fArray.length))
this.fArray[bin] = content;
};
}
if (typename.indexOf("TH1") === 0) {
m.getBin = function (x) {
return x;
};
m.getBinContent = function (bin) {
return this.fArray[bin];
};
m.Fill = function (x, weight) {
var axis = this.fXaxis,
bin = 1 + Math.floor((x - axis.fXmin) / (axis.fXmax - axis.fXmin) * axis.fNbins);
if (bin < 0) bin = 0; else if (bin > axis.fNbins + 1) bin = axis.fNbins + 1;
this.fArray[bin] += ((weight === undefined) ? 1 : weight);
}
}
if (typename.indexOf("TH2") === 0) {
m.getBin = function (x, y) {
return (x + (this.fXaxis.fNbins + 2) * y);
};
m.getBinContent = function (x, y) {
return this.fArray[this.getBin(x, y)];
};
m.Fill = function (x, y, weight) {
var axis1 = this.fXaxis, axis2 = this.fYaxis,
bin1 = 1 + Math.floor((x - axis1.fXmin) / (axis1.fXmax - axis1.fXmin) * axis1.fNbins),
bin2 = 1 + Math.floor((y - axis2.fXmin) / (axis2.fXmax - axis2.fXmin) * axis2.fNbins);
if (bin1 < 0) bin1 = 0; else if (bin1 > axis1.fNbins + 1) bin1 = axis1.fNbins + 1;
if (bin2 < 0) bin2 = 0; else if (bin2 > axis2.fNbins + 1) bin2 = axis2.fNbins + 1;
this.fArray[bin1 + (axis1.fNbins + 2) * bin2] += ((weight === undefined) ? 1 : weight);
}
}
if (typename.indexOf("TH3") === 0) {
m.getBin = function (x, y, z) {
return (x + (this.fXaxis.fNbins + 2) * (y + (this.fYaxis.fNbins + 2) * z));
};
m.getBinContent = function (x, y, z) {
return this.fArray[this.getBin(x, y, z)];
};
m.Fill = function (x, y, z, weight) {
var axis1 = this.fXaxis, axis2 = this.fYaxis, axis3 = this.fZaxis,
bin1 = 1 + Math.floor((x - axis1.fXmin) / (axis1.fXmax - axis1.fXmin) * axis1.fNbins),
bin2 = 1 + Math.floor((y - axis2.fXmin) / (axis2.fXmax - axis2.fXmin) * axis2.fNbins),
bin3 = 1 + Math.floor((z - axis3.fXmin) / (axis3.fXmax - axis3.fXmin) * axis3.fNbins);
if (bin1 < 0) bin1 = 0; else if (bin1 > axis1.fNbins + 1) bin1 = axis1.fNbins + 1;
if (bin2 < 0) bin2 = 0; else if (bin2 > axis2.fNbins + 1) bin2 = axis2.fNbins + 1;
if (bin3 < 0) bin3 = 0; else if (bin3 > axis3.fNbins + 1) bin3 = axis3.fNbins + 1;
this.fArray[bin1 + (axis1.fNbins + 2) * (bin2 + (axis2.fNbins + 2) * bin3)] += ((weight === undefined) ? 1 : weight);
}
}
if (typename.indexOf("TProfile") === 0) {
if (typename.indexOf("TProfile2D") === 0) {
m.getBin = function (x, y) {
return (x + (this.fXaxis.fNbins + 2) * y);
};
m.getBinContent = function (x, y) {
var bin = this.getBin(x, y);
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.getBinEntries = function (x, y) {
var bin = this.getBin(x, y);
if (bin < 0 || bin >= this.fNcells) return 0;
return this.fBinEntries[bin];
}
} else {
m.getBin = function (x) {
return x;
};
m.getBinContent = function (bin) {
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 || this.fBinSumw2.length !== this.fNcells) {
// this can happen when reading an old file
return sumOfWeights;
}
var sumOfWeightsSquare = this.fBinSumw2[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, eprim = Math.sqrt(Math.abs(err2 / sum - contsum * contsum));
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;
};
m.GetBinCenter = function (bin) {
if (this.fNbins <= 0) return 0;
if ((this.fXbins.length > 0) && (bin > 0) && (bin < this.fNbins)) return (this.fXbins[bin - 1] + this.fXbins[bin]) / 2;
return this.fXmin + (bin - 0.5) * (this.fXmax - this.fXmin) / this.fNbins;
}
}
if (typeof getMoreMethods == "function")
getMoreMethods(m, typename, obj);
methodsCache[typename] = m;
return m;
}
/** @summary Adds specific methods to the object.
*
* JSROOT implements some basic methods for different ROOT classes.
* @param {object} obj - object where methods are assigned
* @param {string} typename - optional typename, if not specified, obj._typename will be used
* @private
*/
function addMethods(obj, typename) {
this.extend(obj, getMethods(typename || obj._typename, obj));
}

View File

@ -1,28 +1,12 @@
(function (factory) { import * as THREE from "three-full"
if (typeof define === "function" && define.amd) {
define(['three-full'], factory);
} else if (typeof exports === 'object' && typeof module !== 'undefined') {
factory(require("three-full"), exports);
} else {
if (typeof THREE == 'undefined') const EPSILON = 1e-5,
throw new Error('THREE is not defined', 'ThreeCSG.js');
ThreeBSP = factory(THREE);
}
}(function (THREE, ThreeBSP) {
"use strict";
if (!ThreeBSP) ThreeBSP = {};
var EPSILON = 1e-5,
COPLANAR = 0, COPLANAR = 0,
FRONT = 1, FRONT = 1,
BACK = 2, BACK = 2,
SPANNING = 3; SPANNING = 3;
ThreeBSP.Geometry = function (geometry, transfer_matrix, nodeid, flippedMesh) { export function Geometry(geometry, transfer_matrix, nodeid, flippedMesh) {
// Convert THREE.Geometry to ThreeBSP // Convert THREE.Geometry to ThreeBSP
if (geometry instanceof THREE.Geometry) { if (geometry instanceof THREE.Geometry) {
@ -32,7 +16,7 @@
geometry.updateMatrix(); geometry.updateMatrix();
transfer_matrix = this.matrix = geometry.matrix.clone(); transfer_matrix = this.matrix = geometry.matrix.clone();
geometry = geometry.geometry; geometry = geometry.geometry;
} else if (geometry instanceof ThreeBSP.Node) { } else if (geometry instanceof Node) {
this.tree = geometry; this.tree = geometry;
this.matrix = null; // new THREE.Matrix4; this.matrix = null; // new THREE.Matrix4;
return this; return this;
@ -42,15 +26,15 @@
polygons = [], polygon, vert1, vert2, vert3; polygons = [], polygon, vert1, vert2, vert3;
for (var i = 0; i < pos_buf.length; i += 9) { for (var i = 0; i < pos_buf.length; i += 9) {
polygon = new ThreeBSP.Polygon; polygon = new Polygon;
vert1 = 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]); vert1 = new 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) vert1.applyMatrix4(transfer_matrix); if (transfer_matrix) vert1.applyMatrix4(transfer_matrix);
vert2 = 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]); vert2 = new 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) vert2.applyMatrix4(transfer_matrix); if (transfer_matrix) vert2.applyMatrix4(transfer_matrix);
vert3 = 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]); vert3 = new 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) vert3.applyMatrix4(transfer_matrix); if (transfer_matrix) vert3.applyMatrix4(transfer_matrix);
if (flippedMesh) polygon.vertices.push(vert1, vert3, vert2); if (flippedMesh) polygon.vertices.push(vert1, vert3, vert2);
@ -60,11 +44,11 @@
polygons.push(polygon); polygons.push(polygon);
} }
this.tree = new ThreeBSP.Node(polygons, nodeid); this.tree = new Node(polygons, nodeid);
if (nodeid !== undefined) this.maxid = this.tree.maxnodeid; if (nodeid !== undefined) this.maxid = this.tree.maxnodeid;
return this; return this;
} else if (geometry.polygons && (geometry.polygons[0] instanceof ThreeBSP.Polygon)) { } else if (geometry.polygons && (geometry.polygons[0] instanceof Polygon)) {
var polygons = geometry.polygons; var polygons = geometry.polygons;
for (var i = 0; i < polygons.length; ++i) { for (var i = 0; i < polygons.length; ++i) {
@ -77,7 +61,7 @@
polygon.calculateProperties(); polygon.calculateProperties();
} }
this.tree = new ThreeBSP.Node(polygons, nodeid); this.tree = new Node(polygons, nodeid);
if (nodeid !== undefined) this.maxid = this.tree.maxnodeid; if (nodeid !== undefined) this.maxid = this.tree.maxnodeid;
return this; return this;
@ -92,48 +76,24 @@
for (var i = 0; i < nfaces; ++i) { for (var i = 0; i < nfaces; ++i) {
face = geometry.faces[i]; face = geometry.faces[i];
// faceVertexUvs = geometry.faceVertexUvs[0][i]; // faceVertexUvs = geometry.faceVertexUvs[0][i];
polygon = new ThreeBSP.Polygon; polygon = new Polygon;
if (face instanceof THREE.Face3) { if (face instanceof THREE.Face3) {
vertex = geometry.vertices[face.a]; vertex = geometry.vertices[face.a];
// uvs = faceVertexUvs ? new THREE.Vector2( faceVertexUvs[0].x, faceVertexUvs[0].y ) : null; // uvs = faceVertexUvs ? new THREE.Vector2( faceVertexUvs[0].x, faceVertexUvs[0].y ) : null;
vertex = new ThreeBSP.Vertex(vertex.x, vertex.y, vertex.z, face.vertexNormals[0].x, face.vertexNormals[0].y, face.vertexNormals[0].z /*face.normal , uvs */); vertex = new Vertex(vertex.x, vertex.y, vertex.z, face.vertexNormals[0].x, face.vertexNormals[0].y, face.vertexNormals[0].z /*face.normal , uvs */);
if (transfer_matrix) vertex.applyMatrix4(transfer_matrix); if (transfer_matrix) vertex.applyMatrix4(transfer_matrix);
polygon.vertices.push(vertex); polygon.vertices.push(vertex);
vertex = geometry.vertices[face.b]; vertex = geometry.vertices[face.b];
//uvs = faceVertexUvs ? new THREE.Vector2( faceVertexUvs[1].x, faceVertexUvs[1].y ) : null; //uvs = faceVertexUvs ? new THREE.Vector2( faceVertexUvs[1].x, faceVertexUvs[1].y ) : null;
vertex = new ThreeBSP.Vertex(vertex.x, vertex.y, vertex.z, face.vertexNormals[1].x, face.vertexNormals[1].y, face.vertexNormals[1].z/*face.normal , uvs */); vertex = new Vertex(vertex.x, vertex.y, vertex.z, face.vertexNormals[1].x, face.vertexNormals[1].y, face.vertexNormals[1].z/*face.normal , uvs */);
if (transfer_matrix) vertex.applyMatrix4(transfer_matrix); if (transfer_matrix) vertex.applyMatrix4(transfer_matrix);
polygon.vertices.push(vertex); polygon.vertices.push(vertex);
vertex = geometry.vertices[face.c]; vertex = geometry.vertices[face.c];
// uvs = faceVertexUvs ? new THREE.Vector2( faceVertexUvs[2].x, faceVertexUvs[2].y ) : null; // uvs = faceVertexUvs ? new THREE.Vector2( faceVertexUvs[2].x, faceVertexUvs[2].y ) : null;
vertex = new ThreeBSP.Vertex(vertex.x, vertex.y, vertex.z, face.vertexNormals[2].x, face.vertexNormals[2].y, face.vertexNormals[2].z /*face.normal, uvs */); vertex = new Vertex(vertex.x, vertex.y, vertex.z, face.vertexNormals[2].x, face.vertexNormals[2].y, face.vertexNormals[2].z /*face.normal, uvs */);
if (transfer_matrix) vertex.applyMatrix4(transfer_matrix);
polygon.vertices.push(vertex);
} else if (typeof THREE.Face4) {
vertex = geometry.vertices[face.a];
// uvs = faceVertexUvs ? new THREE.Vector2( faceVertexUvs[0].x, faceVertexUvs[0].y ) : null;
vertex = new ThreeBSP.Vertex(vertex.x, vertex.y, vertex.z, face.vertexNormals[0].x, face.vertexNormals[0].y, face.vertexNormals[0].z /*, uvs */);
if (transfer_matrix) vertex.applyMatrix4(transfer_matrix);
polygon.vertices.push(vertex);
vertex = geometry.vertices[face.b];
// uvs = faceVertexUvs ? new THREE.Vector2( faceVertexUvs[1].x, faceVertexUvs[1].y ) : null;
vertex = new ThreeBSP.Vertex(vertex.x, vertex.y, vertex.z, face.vertexNormals[1].x, face.vertexNormals[1].y, face.vertexNormals[1].z /*, uvs */);
if (transfer_matrix) vertex.applyMatrix4(transfer_matrix);
polygon.vertices.push(vertex);
vertex = geometry.vertices[face.c];
// uvs = faceVertexUvs ? new THREE.Vector2( faceVertexUvs[2].x, faceVertexUvs[2].y ) : null;
vertex = new ThreeBSP.Vertex(vertex.x, vertex.y, vertex.z, face.vertexNormals[2].x, face.vertexNormals[2].y, face.vertexNormals[2].z /*, uvs */);
if (transfer_matrix) vertex.applyMatrix4(transfer_matrix);
polygon.vertices.push(vertex);
vertex = geometry.vertices[face.d];
// uvs = faceVertexUvs ? new THREE.Vector2( faceVertexUvs[3].x, faceVertexUvs[3].y ) : null;
vertex = new ThreeBSP.Vertex(vertex.x, vertex.y, vertex.z, face.vertexNormals[3].x, face.vertexNormals[3].y, face.vertexNormals[3].z /*, uvs */);
if (transfer_matrix) vertex.applyMatrix4(transfer_matrix); if (transfer_matrix) vertex.applyMatrix4(transfer_matrix);
polygon.vertices.push(vertex); polygon.vertices.push(vertex);
} else { } else {
@ -144,11 +104,11 @@
polygons.push(polygon); polygons.push(polygon);
} }
this.tree = new ThreeBSP.Node(polygons, nodeid); this.tree = new Node(polygons, nodeid);
if (nodeid !== undefined) this.maxid = this.tree.maxnodeid; if (nodeid !== undefined) this.maxid = this.tree.maxnodeid;
}; }
ThreeBSP.Geometry.prototype.subtract = function (other_tree) { Geometry.prototype.subtract = function (other_tree) {
var a = this.tree.clone(), var a = this.tree.clone(),
b = other_tree.tree.clone(); b = other_tree.tree.clone();
@ -160,12 +120,12 @@
b.invert(); b.invert();
a.build(b.allPolygons()); a.build(b.allPolygons());
a.invert(); a.invert();
a = new ThreeBSP.Geometry(a); a = new Geometry(a);
a.matrix = this.matrix; a.matrix = this.matrix;
return a; return a;
}; };
ThreeBSP.Geometry.prototype.union = function (other_tree) { Geometry.prototype.union = function (other_tree) {
var a = this.tree.clone(), var a = this.tree.clone(),
b = other_tree.tree.clone(); b = other_tree.tree.clone();
@ -175,12 +135,12 @@
b.clipTo(a); b.clipTo(a);
b.invert(); b.invert();
a.build(b.allPolygons()); a.build(b.allPolygons());
a = new ThreeBSP.Geometry(a); a = new Geometry(a);
a.matrix = this.matrix; a.matrix = this.matrix;
return a; return a;
}; };
ThreeBSP.Geometry.prototype.intersect = function (other_tree) { Geometry.prototype.intersect = function (other_tree) {
var a = this.tree.clone(), var a = this.tree.clone(),
b = other_tree.tree.clone(); b = other_tree.tree.clone();
@ -191,12 +151,12 @@
b.clipTo(a); b.clipTo(a);
a.build(b.allPolygons()); a.build(b.allPolygons());
a.invert(); a.invert();
a = new ThreeBSP.Geometry(a); a = new Geometry(a);
a.matrix = this.matrix; a.matrix = this.matrix;
return a; return a;
}; };
ThreeBSP.Geometry.prototype.tryToCompress = function (polygons) { Geometry.prototype.tryToCompress = function (polygons) {
if (this.maxid === undefined) return; if (this.maxid === undefined) return;
@ -256,9 +216,9 @@
} }
} }
}; };
ThreeBSP.Geometry.prototype.direct_subtract = function (other_tree) { Geometry.prototype.direct_subtract = function (other_tree) {
var a = this.tree, var a = this.tree,
b = other_tree.tree; b = other_tree.tree;
a.invert(); a.invert();
@ -270,9 +230,9 @@
a.build(b.collectPolygons([])); a.build(b.collectPolygons([]));
a.invert(); a.invert();
return this; return this;
}; };
ThreeBSP.Geometry.prototype.direct_union = function (other_tree) { Geometry.prototype.direct_union = function (other_tree) {
var a = this.tree, var a = this.tree,
b = other_tree.tree; b = other_tree.tree;
@ -283,9 +243,9 @@
b.invert(); b.invert();
a.build(b.collectPolygons([])); a.build(b.collectPolygons([]));
return this; return this;
}; };
ThreeBSP.Geometry.prototype.direct_intersect = function (other_tree) { Geometry.prototype.direct_intersect = function (other_tree) {
var a = this.tree, var a = this.tree,
b = other_tree.tree; b = other_tree.tree;
@ -297,9 +257,9 @@
a.build(b.collectPolygons([])); a.build(b.collectPolygons([]));
a.invert(); a.invert();
return this; return this;
}; };
ThreeBSP.CreateNormal = function (axis_name, pos, size) { export function CreateNormal(axis_name, pos, size) {
// create geometry to make cut on specified axis // create geometry to make cut on specified axis
var vert1, vert2, vert3; var vert1, vert2, vert3;
@ -308,32 +268,31 @@
switch (axis_name) { switch (axis_name) {
case "x": case "x":
vert1 = new ThreeBSP.Vertex(pos, -3 * size, size, 1, 0, 0), vert1 = new Vertex(pos, -3 * size, size, 1, 0, 0),
vert3 = new ThreeBSP.Vertex(pos, size, size, 1, 0, 0), vert3 = new Vertex(pos, size, size, 1, 0, 0),
vert2 = new ThreeBSP.Vertex(pos, size, -3 * size, 1, 0, 0); vert2 = new Vertex(pos, size, -3 * size, 1, 0, 0);
break; break;
case "y": case "y":
vert1 = new ThreeBSP.Vertex(-3 * size, pos, size, 0, 1, 0), vert1 = new Vertex(-3 * size, pos, size, 0, 1, 0),
vert2 = new ThreeBSP.Vertex(size, pos, size, 0, 1, 0), vert2 = new Vertex(size, pos, size, 0, 1, 0),
vert3 = new ThreeBSP.Vertex(size, pos, -3 * size, 0, 1, 0); vert3 = new Vertex(size, pos, -3 * size, 0, 1, 0);
break; break;
case "z": case "z":
vert1 = new ThreeBSP.Vertex(-3 * size, size, pos, 0, 0, 1), vert1 = new Vertex(-3 * size, size, pos, 0, 0, 1),
vert3 = new ThreeBSP.Vertex(size, size, pos, 0, 0, 1), vert3 = new Vertex(size, size, pos, 0, 0, 1),
vert2 = new ThreeBSP.Vertex(size, -3 * size, pos, 0, 0, 1); vert2 = new Vertex(size, -3 * size, pos, 0, 0, 1);
break; break;
} }
var polygon = new ThreeBSP.Polygon([vert1, vert2, vert3]); var polygon = new Polygon([vert1, vert2, vert3]);
polygon.calculateProperties(); polygon.calculateProperties();
var node = new ThreeBSP.Node([polygon]); var node = new Node([polygon]);
return new ThreeBSP.Geometry(node); return new Geometry(node);
}; }
Geometry.prototype.cut_from_plane = function (other_tree) {
ThreeBSP.Geometry.prototype.cut_from_plane = function (other_tree) {
// just cut peaces from second geometry, which just simple plane // just cut peaces from second geometry, which just simple plane
var a = this.tree, var a = this.tree,
@ -343,10 +302,10 @@
b.clipTo(a); b.clipTo(a);
return this; return this;
}; };
ThreeBSP.Geometry.prototype.toGeometry = function () { Geometry.prototype.toGeometry = function () {
var i, j, var i, j,
matrix = this.matrix ? new THREE.Matrix4().getInverse(this.matrix) : null, matrix = this.matrix ? new THREE.Matrix4().getInverse(this.matrix) : null,
geometry = new THREE.Geometry(), geometry = new THREE.Geometry(),
@ -411,9 +370,9 @@
} }
return geometry; return geometry;
}; };
ThreeBSP.Geometry.prototype.scale = function (x, y, z) { Geometry.prototype.scale = function (x, y, z) {
// try to scale as THREE.BufferGeometry // try to scale as THREE.BufferGeometry
var polygons = this.tree.collectPolygons([]); var polygons = this.tree.collectPolygons([]);
@ -428,9 +387,9 @@
delete polygon.normal; delete polygon.normal;
polygon.calculateProperties(); polygon.calculateProperties();
} }
}; };
ThreeBSP.Geometry.prototype.toPolygons = function () { Geometry.prototype.toPolygons = function () {
var polygons = this.tree.collectPolygons([]); var polygons = this.tree.collectPolygons([]);
this.tryToCompress(polygons); this.tryToCompress(polygons);
@ -441,13 +400,13 @@
} }
return polygons; return polygons;
}; };
ThreeBSP.Geometry.prototype.toBufferGeometry = function () { Geometry.prototype.toBufferGeometry = function () {
return ThreeBSP.CreateBufferGeometry(this.toPolygons()); return CreateBufferGeometry(this.toPolygons());
}; };
ThreeBSP.CreateBufferGeometry = function (polygons) { export function CreateBufferGeometry(polygons) {
var i, j, polygon_count = polygons.length, buf_size = 0; var i, j, polygon_count = polygons.length, buf_size = 0;
for (i = 0; i < polygon_count; ++i) for (i = 0; i < polygon_count; ++i)
@ -484,9 +443,9 @@
// geometry.computeVertexNormals(); // geometry.computeVertexNormals();
return geometry; return geometry;
}; }
ThreeBSP.Geometry.prototype.toMesh = function (material) { Geometry.prototype.toMesh = function (material) {
var geometry = this.toGeometry(), var geometry = this.toGeometry(),
mesh = new THREE.Mesh(geometry, material); mesh = new THREE.Mesh(geometry, material);
@ -496,9 +455,10 @@
} }
return mesh; return mesh;
}; };
ThreeBSP.Polygon = function (vertices, normal, w) { export class Polygon {
constructor(vertices, normal, w) {
if (!(vertices instanceof Array)) { if (!(vertices instanceof Array)) {
vertices = []; vertices = [];
} }
@ -511,8 +471,10 @@
this.normal = this.w = undefined; this.normal = this.w = undefined;
} }
}; };
}
ThreeBSP.Polygon.prototype.copyProperties = function (parent, more) {
Polygon.prototype.copyProperties = function (parent, more) {
this.normal = parent.normal; // .clone(); this.normal = parent.normal; // .clone();
this.w = parent.w; this.w = parent.w;
this.nsign = parent.nsign; this.nsign = parent.nsign;
@ -521,9 +483,9 @@
this.parent = parent; this.parent = parent;
} }
return this; return this;
}; };
ThreeBSP.Polygon.prototype.calculateProperties = function () { Polygon.prototype.calculateProperties = function () {
if (this.normal) return; if (this.normal) return;
var a = this.vertices[0], var a = this.vertices[0],
@ -538,19 +500,19 @@
this.w = this.normal.clone().dot(a); this.w = this.normal.clone().dot(a);
return this; return this;
}; };
ThreeBSP.Polygon.prototype.clone = function () { Polygon.prototype.clone = function () {
var vertice_count = this.vertices.length, var vertice_count = this.vertices.length,
polygon = new ThreeBSP.Polygon; polygon = new Polygon;
for (var i = 0; i < vertice_count; ++i) for (var i = 0; i < vertice_count; ++i)
polygon.vertices.push(this.vertices[i].clone()); polygon.vertices.push(this.vertices[i].clone());
return polygon.copyProperties(this); return polygon.copyProperties(this);
}; };
ThreeBSP.Polygon.prototype.flip = function () { Polygon.prototype.flip = function () {
/// normal is not changed, only sign variable /// normal is not changed, only sign variable
//this.normal.multiplyScalar( -1 ); //this.normal.multiplyScalar( -1 );
@ -561,17 +523,17 @@
this.vertices.reverse(); this.vertices.reverse();
return this; return this;
}; };
ThreeBSP.Polygon.prototype.classifyVertex = function (vertex) { Polygon.prototype.classifyVertex = function (vertex) {
var side_value = this.nsign * (this.normal.dot(vertex) - this.w); var side_value = this.nsign * (this.normal.dot(vertex) - this.w);
if (side_value < -EPSILON) return BACK; if (side_value < -EPSILON) return BACK;
if (side_value > EPSILON) return FRONT; if (side_value > EPSILON) return FRONT;
return COPLANAR; return COPLANAR;
}; };
ThreeBSP.Polygon.prototype.classifySide = function (polygon) { Polygon.prototype.classifySide = function (polygon) {
var i, classification, var i, classification,
num_positive = 0, num_negative = 0, num_positive = 0, num_negative = 0,
vertice_count = polygon.vertices.length; vertice_count = polygon.vertices.length;
@ -589,9 +551,9 @@
if (num_positive === 0 && num_negative > 0) return BACK; if (num_positive === 0 && num_negative > 0) return BACK;
if (num_positive === 0 && num_negative === 0) return COPLANAR; if (num_positive === 0 && num_negative === 0) return COPLANAR;
return SPANNING; return SPANNING;
}; };
ThreeBSP.Polygon.prototype.splitPolygon = function (polygon, coplanar_front, coplanar_back, front, back) { Polygon.prototype.splitPolygon = function (polygon, coplanar_front, coplanar_back, front, back) {
var classification = this.classifySide(polygon); var classification = this.classifySide(polygon);
if (classification === COPLANAR) { if (classification === COPLANAR) {
@ -638,14 +600,15 @@
} }
} }
//if ( f.length >= 3 ) front.push( new ThreeBSP.Polygon( f ).calculateProperties() ); //if ( f.length >= 3 ) front.push( new Polygon( f ).calculateProperties() );
//if ( b.length >= 3 ) back.push( new ThreeBSP.Polygon( b ).calculateProperties() ); //if ( b.length >= 3 ) back.push( new Polygon( b ).calculateProperties() );
if (f.length >= 3) front.push(new ThreeBSP.Polygon(f).copyProperties(polygon, true)); if (f.length >= 3) front.push(new Polygon(f).copyProperties(polygon, true));
if (b.length >= 3) back.push(new ThreeBSP.Polygon(b).copyProperties(polygon, true)); if (b.length >= 3) back.push(new Polygon(b).copyProperties(polygon, true));
} }
}; };
ThreeBSP.Vertex = function (x, y, z, nx, ny, nz) { export class Vertex {
constructor(x, y, z, nx, ny, nz) {
this.x = x; this.x = x;
this.y = y; this.y = y;
this.z = z; this.z = z;
@ -653,39 +616,40 @@
this.ny = ny; this.ny = ny;
this.nz = nz; this.nz = nz;
}; };
}
ThreeBSP.Vertex.prototype.setnormal = function (nx, ny, nz) { Vertex.prototype.setnormal = function (nx, ny, nz) {
this.nx = nx; this.nx = nx;
this.ny = ny; this.ny = ny;
this.nz = nz; this.nz = nz;
}; };
ThreeBSP.Vertex.prototype.clone = function () { Vertex.prototype.clone = function () {
return new ThreeBSP.Vertex(this.x, this.y, this.z, this.nx, this.ny, this.nz); return new Vertex(this.x, this.y, this.z, this.nx, this.ny, this.nz);
}; };
ThreeBSP.Vertex.prototype.add = function (vertex) { Vertex.prototype.add = function (vertex) {
this.x += vertex.x; this.x += vertex.x;
this.y += vertex.y; this.y += vertex.y;
this.z += vertex.z; this.z += vertex.z;
return this; return this;
}; };
ThreeBSP.Vertex.prototype.subtract = function (vertex) { Vertex.prototype.subtract = function (vertex) {
this.x -= vertex.x; this.x -= vertex.x;
this.y -= vertex.y; this.y -= vertex.y;
this.z -= vertex.z; this.z -= vertex.z;
return this; return this;
}; };
ThreeBSP.Vertex.prototype.multiplyScalar = function (scalar) { Vertex.prototype.multiplyScalar = function (scalar) {
this.x *= scalar; this.x *= scalar;
this.y *= scalar; this.y *= scalar;
this.z *= scalar; this.z *= scalar;
return this; return this;
}; };
ThreeBSP.Vertex.prototype.cross = function (vertex) { Vertex.prototype.cross = function (vertex) {
var x = this.x, var x = this.x,
y = this.y, y = this.y,
z = this.z; z = this.z;
@ -695,9 +659,9 @@
this.z = x * vertex.y - y * vertex.x; this.z = x * vertex.y - y * vertex.x;
return this; return this;
}; };
ThreeBSP.Vertex.prototype.normalize = function () { Vertex.prototype.normalize = function () {
var length = Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); var length = Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
this.x /= length; this.x /= length;
@ -705,23 +669,23 @@
this.z /= length; this.z /= length;
return this; return this;
}; };
ThreeBSP.Vertex.prototype.dot = function (vertex) { Vertex.prototype.dot = function (vertex) {
return this.x * vertex.x + this.y * vertex.y + this.z * vertex.z; return this.x * vertex.x + this.y * vertex.y + this.z * vertex.z;
}; };
ThreeBSP.Vertex.prototype.diff = function (vertex) { Vertex.prototype.diff = function (vertex) {
var dx = (this.x - vertex.x), var dx = (this.x - vertex.x),
dy = (this.y - vertex.y), dy = (this.y - vertex.y),
dz = (this.z - vertex.z), dz = (this.z - vertex.z),
len2 = this.x * this.x + this.y * this.y + this.z * this.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); return (dx * dx + dy * dy + dz * dz) / (len2 > 0 ? len2 : 1e-10);
}; };
/* /*
ThreeBSP.Vertex.prototype.lerp = function( a, t ) { Vertex.prototype.lerp = function( a, t ) {
this.add( this.add(
a.clone().subtract( this ).multiplyScalar( t ) a.clone().subtract( this ).multiplyScalar( t )
); );
@ -736,18 +700,18 @@
return this; return this;
}; };
ThreeBSP.Vertex.prototype.interpolate = function( other, t ) { Vertex.prototype.interpolate = function( other, t ) {
return this.clone().lerp( other, t ); return this.clone().lerp( other, t );
}; };
*/ */
ThreeBSP.Vertex.prototype.interpolate = function (a, t) { Vertex.prototype.interpolate = function (a, t) {
var t1 = 1 - 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, return new 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); this.nx * t1 + a.nx * t, this.ny * t1 + a.ny * t, this.nz * t1 + a.nz * t);
}; };
ThreeBSP.Vertex.prototype.applyMatrix4 = function (m) { Vertex.prototype.applyMatrix4 = function (m) {
// input: THREE.Matrix4 affine matrix // input: THREE.Matrix4 affine matrix
@ -766,11 +730,12 @@
this.nz = e[2] * x + e[6] * y + e[10] * z; this.nz = e[2] * x + e[6] * y + e[10] * z;
return this; return this;
}; };
// ================================================================================================ // ================================================================================================
ThreeBSP.Node = function (polygons, nodeid) { export class Node {
constructor(polygons, nodeid) {
this.polygons = []; this.polygons = [];
this.front = this.back = undefined; this.front = this.back = undefined;
@ -793,21 +758,22 @@
if (nodeid !== undefined) this.maxnodeid = nodeid; if (nodeid !== undefined) this.maxnodeid = nodeid;
if (front.length > 0) if (front.length > 0)
this.front = new ThreeBSP.Node(front); this.front = new Node(front);
if (back.length > 0) if (back.length > 0)
this.back = new ThreeBSP.Node(back); this.back = new Node(back);
}; };
}
ThreeBSP.Node.isConvex = function (polygons) { Node.isConvex = function (polygons) {
var i, j, len = polygons.length; var i, j, len = polygons.length;
for (i = 0; i < len; ++i) for (i = 0; i < len; ++i)
for (j = 0; j < len; ++j) for (j = 0; j < len; ++j)
if (i !== j && polygons[i].classifySide(polygons[j]) !== BACK) return false; if (i !== j && polygons[i].classifySide(polygons[j]) !== BACK) return false;
return true; return true;
}; };
ThreeBSP.Node.prototype.build = function (polygons) { Node.prototype.build = function (polygons) {
var polygon_count = polygons.length, var polygon_count = polygons.length,
front = [], back = []; front = [], back = [];
@ -818,40 +784,40 @@
this.divider.splitPolygon(polygons[i], this.polygons, this.polygons, front, back); this.divider.splitPolygon(polygons[i], this.polygons, this.polygons, front, back);
if (front.length > 0) { if (front.length > 0) {
if (!this.front) this.front = new ThreeBSP.Node(); if (!this.front) this.front = new Node();
this.front.build(front); this.front.build(front);
} }
if (back.length > 0) { if (back.length > 0) {
if (!this.back) this.back = new ThreeBSP.Node(); if (!this.back) this.back = new Node();
this.back.build(back); this.back.build(back);
} }
}; };
ThreeBSP.Node.prototype.collectPolygons = function (arr) { Node.prototype.collectPolygons = function (arr) {
var len = this.polygons.length; var len = this.polygons.length;
for (var i = 0; i < len; ++i) arr.push(this.polygons[i]); for (var i = 0; i < len; ++i) arr.push(this.polygons[i]);
if (this.front) this.front.collectPolygons(arr); if (this.front) this.front.collectPolygons(arr);
if (this.back) this.back.collectPolygons(arr); if (this.back) this.back.collectPolygons(arr);
return arr; return arr;
}; };
ThreeBSP.Node.prototype.allPolygons = function () { Node.prototype.allPolygons = function () {
var polygons = this.polygons.slice(); var polygons = this.polygons.slice();
if (this.front) polygons = polygons.concat(this.front.allPolygons()); if (this.front) polygons = polygons.concat(this.front.allPolygons());
if (this.back) polygons = polygons.concat(this.back.allPolygons()); if (this.back) polygons = polygons.concat(this.back.allPolygons());
return polygons; return polygons;
}; };
ThreeBSP.Node.prototype.numPolygons = function () { Node.prototype.numPolygons = function () {
var res = this.polygons.length; var res = this.polygons.length;
if (this.front) res += this.front.numPolygons(); if (this.front) res += this.front.numPolygons();
if (this.back) res += this.back.numPolygons(); if (this.back) res += this.back.numPolygons();
return res; return res;
}; };
ThreeBSP.Node.prototype.clone = function () { Node.prototype.clone = function () {
var node = new ThreeBSP.Node(); var node = new Node();
node.divider = this.divider.clone(); node.divider = this.divider.clone();
node.polygons = this.polygons.map(function (polygon) { node.polygons = this.polygons.map(function (polygon) {
@ -861,9 +827,9 @@
node.back = this.back && this.back.clone(); node.back = this.back && this.back.clone();
return node; return node;
}; };
ThreeBSP.Node.prototype.invert = function () { Node.prototype.invert = function () {
var polygon_count = this.polygons.length; var polygon_count = this.polygons.length;
for (var i = 0; i < polygon_count; ++i) for (var i = 0; i < polygon_count; ++i)
@ -878,9 +844,9 @@
this.back = temp; this.back = temp;
return this; return this;
}; };
ThreeBSP.Node.prototype.clipPolygons = function (polygons) { Node.prototype.clipPolygons = function (polygons) {
if (!this.divider) return polygons.slice(); if (!this.divider) return polygons.slice();
@ -894,15 +860,10 @@
else back = []; else back = [];
return front.concat(back); return front.concat(back);
}; };
ThreeBSP.Node.prototype.clipTo = function (node) { Node.prototype.clipTo = function (node) {
this.polygons = node.clipPolygons(this.polygons); this.polygons = node.clipPolygons(this.polygons);
if (this.front) this.front.clipTo(node); if (this.front) this.front.clipTo(node);
if (this.back) this.back.clipTo(node); if (this.back) this.back.clipTo(node);
}; };
return ThreeBSP;
}));