"use strict";
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.HVec3 = void 0;
/*
 * @Description  : arbitrary-precision 任意精度的向量
 * @Author       : 赵耀圣
 * @QQ           : 549184003
 * @Date         : 2021-08-02 16:24:03
 * @LastEditTime : 2021-08-03 11:32:10
 * @FilePath     : \cga.js\src\math\HVec3.ts
 */
var eventhandler_1 = require("../render/eventhandler");
var decimal_js_1 = __importDefault(require("decimal.js"));
var HVec3 = /** @class */ (function (_super) {
    __extends(HVec3, _super);
    function HVec3(_x, _y, _z) {
        if (_x === void 0) { _x = 0; }
        if (_y === void 0) { _y = 0; }
        if (_z === void 0) { _z = 0; }
        var _this = _super.call(this) || this;
        _this._x = _x;
        _this._y = _y;
        _this._z = _z;
        _this.x = new decimal_js_1.default(_x);
        _this.y = new decimal_js_1.default(_x);
        _this.z = new decimal_js_1.default(_x);
        return _this;
    }
    HVec3.isVec3 = function (v) {
        return !isNaN(v.x) && !isNaN(v.y) && !isNaN(v.z) && isNaN(v.w);
    };
    Object.defineProperty(HVec3.prototype, "isVec3", {
        get: function () { return true; },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(HVec3, "Up", {
        get: function () {
            return new HVec3(0, 1, 0);
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(HVec3, "Down", {
        get: function () {
            return new HVec3(0, 1, 0);
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(HVec3, "UnitX", {
        get: function () {
            return new HVec3(1, 0, 0);
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(HVec3, "UnitY", {
        get: function () {
            return new HVec3(0, 1, 0);
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(HVec3, "UnitZ", {
        get: function () {
            return new HVec3(0, 0, 1);
        },
        enumerable: false,
        configurable: true
    });
    HVec3.prototype.set = function (x, y, z) {
        this.x = x;
        this.y = y;
        this.z = z;
        return this;
    };
    HVec3.prototype.setScalar = function (scalar) {
        this.x = scalar;
        this.y = scalar;
        this.z = scalar;
        return this;
    };
    HVec3.prototype.setComponent = function (index, value) {
        switch (index) {
            case 0:
                this.x = value;
                break;
            case 1:
                this.y = value;
                break;
            case 2:
                this.z = value;
                break;
            default:
                throw new Error("index is out of range: " + index);
        }
        return this;
    };
    HVec3.prototype.add = function (v, w) {
        if (w !== undefined) {
            console.warn("Vec3: .add() now only accepts one argument. Use .addVecs( a, b ) instead.");
            return this.addVecs(v, w);
        }
        this.x.add(v.x);
        this.y.add(v.y);
        this.z.add(v.z);
        return this;
    };
    HVec3.prototype.addVecs = function (a, b) {
        this.x = new decimal_js_1.default(a.x).add(b.x);
        this.y = new decimal_js_1.default(a.y).add(b.y);
        this.z = new decimal_js_1.default(a.z).add(b.z);
        return this;
    };
    HVec3.prototype.sub = function (v, w) {
        if (w !== undefined) {
            console.warn("Vec3: .sub() now only accepts one argument. Use .subVecs( a, b ) instead.");
            return this.subVecs(v, w);
        }
        this.x.sub(v.x);
        this.y.sub(v.y);
        this.z.sub(v.z);
        return this;
    };
    HVec3.prototype.subVecs = function (a, b) {
        this.x = new decimal_js_1.default(a.x).sub(b.x);
        this.y = new decimal_js_1.default(a.y).sub(b.y);
        this.z = new decimal_js_1.default(a.z).sub(b.z);
        return this;
    };
    HVec3.prototype.multiplyScalar = function (scalar) {
        scalar = new decimal_js_1.default(scalar);
        this.x.mul(scalar);
        this.y.mul(scalar);
        this.z.mul(scalar);
        return this;
    };
    HVec3.prototype.cross = function (v, w) {
        if (w !== undefined) {
            console.warn("Vec3: .cross() now only accepts one argument. Use .crossVecs( a, b ) instead.");
            return this.crossVecs(v, w);
        }
        return this.crossVecs(this, v);
    };
    HVec3.prototype.crossVecs = function (a, b) {
        var ax = a.x, ay = a.y, az = a.z;
        var bx = b.x, by = b.y, bz = b.z;
        this.x = ay.mul(bz).sub(az.mul(by));
        this.y = az.mul(bx).sub(ax.mul(bz));
        this.z = ax.mul(by).sub(ay.mul(bx));
        return this;
    };
    HVec3.prototype.dot = function (v) {
        return this.x.mul(v.x).add(this.y.mul(v.y)).add(this.z.mul(v.z));
    };
    HVec3.prototype.lerp = function (v, alpha) {
        this.x.add(v.x.sub(this.x).mul(alpha));
        this.y.add(v.y.sub(this.y).mul(alpha));
        this.z.add(v.z.sub(this.z).mul(alpha));
        return this;
    };
    HVec3.prototype.clone = function () {
        return new HVec3(this.x, this.y, this.z);
    };
    HVec3.prototype.length = function () {
        return this.x.mul(this.x).add(this.y.mul(this.y)).add(this.z.mul(this.z)).sqrt();
    };
    HVec3.prototype.normalize = function () {
        return this.divideScalar(this.length() || new decimal_js_1.default(1));
    };
    HVec3.prototype.divideScalar = function (scalar) {
        return this.multiplyScalar(new decimal_js_1.default(1).mul(new decimal_js_1.default(scalar)));
    };
    return HVec3;
}(eventhandler_1.EventHandler));
exports.HVec3 = HVec3;
