// namespaces
var dwv = dwv || {};
dwv.math = dwv.math || {};
/**
* Mulitply the three inputs if the last two are not null.
*
* @param {number} a The first input.
* @param {number} b The second input.
* @param {number} c The third input.
* @returns {number} The multiplication of the three inputs or
* null if one of the last two is null.
*/
dwv.math.mulABC = function (a, b, c) {
var res = null;
if (b !== null && c !== null) {
res = a * b * c;
}
return res;
};
/**
* Ellipse shape.
*
* @class
* @param {dwv.math.Point2D} centre A Point2D representing the centre
* of the ellipse.
* @param {number} a The radius of the ellipse on the horizontal axe.
* @param {number} b The radius of the ellipse on the vertical axe.
*/
dwv.math.Ellipse = function (centre, a, b) {
/**
* Get the centre (point) of the ellipse.
*
* @returns {dwv.math.Point2D} The center (point) of the ellipse.
*/
this.getCenter = function () {
return centre;
};
/**
* Get the radius of the ellipse on the horizontal axe.
*
* @returns {number} The radius of the ellipse on the horizontal axe.
*/
this.getA = function () {
return a;
};
/**
* Get the radius of the ellipse on the vertical axe.
*
* @returns {number} The radius of the ellipse on the vertical axe.
*/
this.getB = function () {
return b;
};
}; // Ellipse class
/**
* Check for equality.
*
* @param {dwv.math.Ellipse} rhs The object to compare to.
* @returns {boolean} True if both objects are equal.
*/
dwv.math.Ellipse.prototype.equals = function (rhs) {
return rhs !== null &&
this.getCenter().equals(rhs.getCenter()) &&
this.getA() === rhs.getA() &&
this.getB() === rhs.getB();
};
/**
* Get the surface of the ellipse.
*
* @returns {number} The surface of the ellipse.
*/
dwv.math.Ellipse.prototype.getSurface = function () {
return Math.PI * this.getA() * this.getB();
};
/**
* Get the surface of the ellipse according to a spacing.
*
* @param {number} spacingX The X spacing.
* @param {number} spacingY The Y spacing.
* @returns {number} The surface of the ellipse multiplied by the given
* spacing or null for null spacings.
*/
dwv.math.Ellipse.prototype.getWorldSurface = function (spacingX, spacingY) {
return dwv.math.mulABC(this.getSurface(), spacingX, spacingY);
};
/**
* Get the rounded limits of the ellipse.
* (see https://en.wikipedia.org/wiki/Ellipse#Standard_equation)
* Ellipse formula: x*x / a*a + y*y / b*b = 1
* => y = (+-)(b/a) * sqrt(a*a - x*x)
*
* @returns {Array} The rounded limits.
*/
dwv.math.Ellipse.prototype.getRound = function () {
var centerX = this.getCenter().getX();
var centerY = this.getCenter().getY();
var radiusX = this.getA();
var radiusY = this.getB();
var radiusRatio = radiusX / radiusY;
var rySquare = Math.pow(radiusY, 2);
// Y bounds
var minY = centerY - radiusY;
var maxY = centerY + radiusY;
var regions = [];
// loop through lines and store limits
for (var y = minY; y < maxY; ++y) {
var diff = rySquare - Math.pow(y - centerY, 2);
// remove small values (possibly negative)
if (Math.abs(diff) < 1e-7) {
continue;
}
var transX = radiusRatio * Math.sqrt(diff);
// remove small values
if (transX < 0.5) {
continue;
}
regions.push([
[Math.round(centerX - transX), Math.round(y)],
[Math.round(centerX + transX), Math.round(y)]
]);
}
return regions;
};
/**
* Quantify an ellipse according to view information.
*
* @param {dwv.ctrl.ViewController} viewController The associated view
* controller.
* @param {Array} flags A list of stat values to calculate.
* @returns {object} A quantification object.
*/
dwv.math.Ellipse.prototype.quantify = function (viewController, flags) {
var quant = {};
// surface
var spacing = viewController.get2DSpacing();
var surface = this.getWorldSurface(spacing[0], spacing[1]);
if (surface !== null) {
quant.surface = {value: surface / 100, unit: dwv.i18n('unit.cm2')};
}
// pixel quantification
if (viewController.canQuantifyImage()) {
var regions = this.getRound();
if (regions.length !== 0) {
var values = viewController.getImageVariableRegionValues(regions);
var quantif = dwv.math.getStats(values, flags);
quant.min = {value: quantif.getMin(), unit: ''};
quant.max = {value: quantif.getMax(), unit: ''};
quant.mean = {value: quantif.getMean(), unit: ''};
quant.stdDev = {value: quantif.getStdDev(), unit: ''};
if (typeof quantif.getMedian !== 'undefined') {
quant.median = {value: quantif.getMedian(), unit: ''};
}
if (typeof quantif.getP25 !== 'undefined') {
quant.p25 = {value: quantif.getP25(), unit: ''};
}
if (typeof quantif.getP75 !== 'undefined') {
quant.p75 = {value: quantif.getP75(), unit: ''};
}
}
}
// return
return quant;
};