2749 lines
92 KiB
JavaScript
2749 lines
92 KiB
JavaScript
/*
|
||
* (c) Copyright Ascensio System SIA 2010-2024
|
||
*
|
||
* This program is a free software product. You can redistribute it and/or
|
||
* modify it under the terms of the GNU Affero General Public License (AGPL)
|
||
* version 3 as published by the Free Software Foundation. In accordance with
|
||
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
|
||
* that Ascensio System SIA expressly excludes the warranty of non-infringement
|
||
* of any third-party rights.
|
||
*
|
||
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
|
||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
|
||
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||
*
|
||
* You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
|
||
* street, Riga, Latvia, EU, LV-1050.
|
||
*
|
||
* The interactive user interfaces in modified source and object code versions
|
||
* of the Program must display Appropriate Legal Notices, as required under
|
||
* Section 5 of the GNU AGPL version 3.
|
||
*
|
||
* Pursuant to Section 7(b) of the License you must retain the original Product
|
||
* logo when distributing the program. Pursuant to Section 7(e) we decline to
|
||
* grant you any rights under trademark law for use of our trademarks.
|
||
*
|
||
* All the Product's GUI elements, including illustrations and icon sets, as
|
||
* well as technical writing content are licensed under the terms of the
|
||
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
|
||
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||
*
|
||
*/
|
||
|
||
"use strict";
|
||
|
||
(/**
|
||
* @param {Window} window
|
||
* @param {undefined} undefined
|
||
*/
|
||
function (window, undefined) {
|
||
|
||
// Import
|
||
let ORIENTATION_MIN_MAX = AscFormat.ORIENTATION_MIN_MAX;
|
||
|
||
let globalBasePercent = 100;
|
||
let global3DPersperctive = 30; // ToDo а нужна ли она в ChartsDrawer ?
|
||
|
||
let c_oChartFloorPosition = {
|
||
None: 0, Left: 1, Right: 2, Bottom: 3, Top: 4
|
||
};
|
||
|
||
/** @constructor */
|
||
function Processor3D(width, height, left, right, bottom, top, chartSpace, chartsDrawer) {
|
||
this.widthCanvas = width;
|
||
this.heightCanvas = height;
|
||
|
||
this.left = left ? left : 0;
|
||
this.right = right ? right : 0;
|
||
this.bottom = bottom ? bottom : 0;
|
||
this.top = top ? top : 0;
|
||
|
||
this.cameraDiffZ = 0;
|
||
this.cameraDiffX = 0;
|
||
this.cameraDiffY = 0;
|
||
|
||
this.scaleY = 1;
|
||
this.scaleX = 1;
|
||
this.scaleZ = 1;
|
||
|
||
this.aspectRatioY = 1;
|
||
this.aspectRatioX = 1;
|
||
this.aspectRatioZ = 1;
|
||
|
||
this.specialStandardScaleX = 1;
|
||
|
||
this.view3D = chartSpace.chart.getView3d();
|
||
this.chartSpace = chartSpace;
|
||
this.chartsDrawer = chartsDrawer;
|
||
|
||
this.rPerspective = 0;
|
||
|
||
this.hPercent = null;
|
||
|
||
this.angleOx = this.view3D && this.view3D.rotX ? (-this.view3D.rotX / 360) * (Math.PI * 2) : 0;
|
||
this.angleOy = this.view3D && this.view3D.rotY ? (-this.view3D.rotY / 360) * (Math.PI * 2) : 0;
|
||
//this.angleOz = this.view3D && this.view3D.rotZ ? (- this.view3D.rotZ / 360) * (Math.PI * 2) : 0;
|
||
|
||
if (!this.view3D.getRAngAx() && AscFormat.c_oChartTypes.Pie === this.chartsDrawer.calcProp.type) {
|
||
this.angleOy = 0;
|
||
}
|
||
|
||
this.orientationCatAx = null;
|
||
this.orientationValAx = null;
|
||
|
||
this.matrixRotateOx = null;
|
||
this.matrixRotateOy = null;
|
||
this.matrixRotateAllAxis = null;
|
||
this.matrixShearXY = null;
|
||
this.projectMatrix = null;
|
||
}
|
||
|
||
Processor3D.prototype.calaculate3DProperties = function (baseDepth, gapDepth, bIsCheck) {
|
||
this.calculateCommonOptions();
|
||
|
||
//TODO baseDepth - не универсальный параметр, позже переделать
|
||
this._calculateAutoHPercent();
|
||
|
||
//рассчёт коэффициэнта отношения ширины / высоты
|
||
this._calcAspectRatio();
|
||
|
||
//TODO рассчёт коэффицианты для диаграмм типа standard. позже необходимо отказаться
|
||
//this._calcSpecialStandardScaleX();
|
||
|
||
//глубина
|
||
this.depthPerspective = this.view3D.getRAngAx() ? this._calculateDepth() : this._calculateDepthPerspective();
|
||
|
||
//угол перспективы
|
||
this._calculatePerspective(this.view3D);
|
||
|
||
//после рассчета глубины меняются пропорции ширины и высоты
|
||
if (this.view3D.getRAngAx()) {
|
||
this._calculateScaleFromDepth();
|
||
}
|
||
|
||
//сдвиг камеры для того, чтобы попали все линии
|
||
if (!bIsCheck) {
|
||
this._calculateCameraDiff();
|
||
|
||
if (this.view3D.getRAngAx()) {
|
||
this._recalculateScaleWithMaxWidth();
|
||
}
|
||
}
|
||
|
||
if (AscFormat.c_oChartTypes.Pie === this.chartsDrawer.calcProp.type && !this.view3D.getRAngAx()) {
|
||
//TODO пересмотреть функцию
|
||
this.tempChangeAspectRatioForPie();
|
||
}
|
||
};
|
||
|
||
Processor3D.prototype.tempChangeAspectRatioForPie = function () {
|
||
let perspectiveDepth = this.depthPerspective;
|
||
|
||
let widthCanvas = this.widthCanvas;
|
||
let originalWidthChart = widthCanvas - this.left - this.right;
|
||
|
||
let heightCanvas = this.heightCanvas;
|
||
let heightChart = heightCanvas - this.top - this.bottom;
|
||
|
||
let points = [], faces = [];
|
||
|
||
points.push(new Point3D(this.left + originalWidthChart / 2, this.top, perspectiveDepth, this));
|
||
points.push(new Point3D(this.left, this.top, perspectiveDepth / 2, this));
|
||
points.push(new Point3D(this.left + originalWidthChart, this.top, perspectiveDepth / 2, this));
|
||
points.push(new Point3D(this.left + originalWidthChart / 2, this.top, 0, this));
|
||
|
||
points.push(new Point3D(this.left + originalWidthChart / 2, this.top + heightChart, perspectiveDepth, this));
|
||
points.push(new Point3D(this.left, this.top + heightChart, perspectiveDepth / 2, this));
|
||
points.push(new Point3D(this.left + originalWidthChart, this.top + heightChart, perspectiveDepth / 2, this));
|
||
points.push(new Point3D(this.left + originalWidthChart / 2, this.top + heightChart, 0, this));
|
||
|
||
faces.push([0, 1, 2, 3]);
|
||
faces.push([2, 5, 4, 3]);
|
||
faces.push([1, 6, 7, 0]);
|
||
faces.push([6, 5, 4, 7]);
|
||
faces.push([7, 4, 3, 0]);
|
||
faces.push([1, 6, 2, 5]);
|
||
|
||
let minMaxOx = this._getMinMaxOx(points, faces);
|
||
let minMaxOy = this._getMinMaxOy(points, faces);
|
||
|
||
let kF = ((minMaxOx.right - minMaxOx.left) / originalWidthChart);
|
||
if ((minMaxOy.bottom - minMaxOy.top) / kF > heightChart) {
|
||
kF = ((minMaxOy.bottom - minMaxOy.top) / heightChart);
|
||
}
|
||
|
||
this.aspectRatioX = this.aspectRatioX * kF;
|
||
this.aspectRatioY = this.aspectRatioY * kF;
|
||
this.aspectRatioZ = this.aspectRatioZ * kF;
|
||
};
|
||
|
||
Processor3D.prototype.calculateCommonOptions = function () {
|
||
this.orientationCatAx = this.chartSpace && this.chartSpace.chart.plotArea.catAx ? this.chartSpace.chart.plotArea.catAx.getOrientation() : ORIENTATION_MIN_MAX;
|
||
this.orientationValAx = this.chartSpace && this.chartSpace.chart.plotArea.valAx ? this.chartSpace.chart.plotArea.valAx.getOrientation() : ORIENTATION_MIN_MAX;
|
||
};
|
||
|
||
Processor3D.prototype._calculateAutoHPercent = function () {
|
||
let widthLine = this.widthCanvas - (this.left + this.right);
|
||
let heightLine = this.heightCanvas - (this.top + this.bottom);
|
||
|
||
if (this.hPercent == null) {
|
||
this.hPercent = this.view3D.hPercent === null ? (heightLine / widthLine) : this.view3D.hPercent / 100;
|
||
if (this.chartsDrawer.calcProp.type === AscFormat.c_oChartTypes.HBar &&
|
||
((this.view3D.hPercent === null && this.view3D.getRAngAx()) || (this.view3D.hPercent !== null && !this.view3D.getRAngAx()))) {
|
||
this.hPercent = 1 / this.hPercent;
|
||
}
|
||
|
||
if (AscFormat.c_oChartTypes.Pie === this.chartsDrawer.calcProp.type) {
|
||
this.hPercent = 0.12;
|
||
//this.view3D.depthPercent = 180;
|
||
}
|
||
|
||
}
|
||
};
|
||
|
||
Processor3D.prototype._recalculateScaleWithMaxWidth = function () {
|
||
let widthLine = this.widthCanvas - (this.left + this.right);
|
||
let heightLine = this.heightCanvas - (this.top + this.bottom);
|
||
let widthCanvas = this.widthCanvas;
|
||
//todo оптимальную ширину нужно пересмотреть
|
||
//оптимальная ширина - ширина при которой не происходит масштабирования по ширине
|
||
let optimalWidth = heightLine * 10;
|
||
|
||
let subType = this.chartsDrawer.calcProp.subType;
|
||
let type = this.chartsDrawer.calcProp.type;
|
||
let isStandardType = subType === "standard" || type === AscFormat.c_oChartTypes.Line || (type === AscFormat.c_oChartTypes.Area && subType === "normal") || type ===
|
||
AscFormat.c_oChartTypes.Surface;
|
||
|
||
let optimalWidthLine, kF;
|
||
if (!isStandardType) {
|
||
this.widthCanvas = optimalWidth + (this.left + this.right);
|
||
this._calculateScaleNStandard();
|
||
optimalWidthLine = Math.abs(this.depthPerspective * Math.sin(-this.angleOy)) + ((this.widthCanvas - (this.left + this.right)) / this.aspectRatioX) / this.scaleX;
|
||
kF = optimalWidthLine / widthLine;
|
||
|
||
if (optimalWidthLine < widthLine) {
|
||
this.widthCanvas = widthCanvas;
|
||
this._calculateScaleNStandard();
|
||
} else {
|
||
this.aspectRatioX = widthLine / ((optimalWidthLine - Math.abs(this.depthPerspective * Math.sin(-this.angleOy))) / kF);
|
||
this.scaleY = this.scaleY * kF;
|
||
this.scaleZ = this.scaleZ * kF;
|
||
|
||
this.widthCanvas = widthCanvas;
|
||
}
|
||
|
||
this._recalculateCameraDiff();
|
||
} else {
|
||
let scaleX = this.scaleX;
|
||
let scaleY = this.scaleY;
|
||
let scaleZ = this.scaleZ;
|
||
|
||
let aspectRatioX = this.aspectRatioX;
|
||
let aspectRatioY = this.aspectRatioY;
|
||
let aspectRatioZ = this.aspectRatioZ;
|
||
|
||
//если будут проблемы с поворотом standard диграмм, раскомментровать!
|
||
//TODO протестировать, и если не будет проблем, то убрать if-else
|
||
if (Math.abs(this.angleOy) > Math.PI) {
|
||
//рассчитываем параметры диаграммы при оптимальной ширине
|
||
this.widthCanvas = optimalWidth + (this.left + this.right);
|
||
|
||
this.calaculate3DProperties(null, null, true);
|
||
|
||
let newDepth = Math.abs(this.depthPerspective * Math.sin(-this.angleOy));
|
||
optimalWidthLine = newDepth + ((this.widthCanvas - (this.left + this.right)) / this.aspectRatioX) / this.scaleX;
|
||
kF = optimalWidthLine / widthLine;
|
||
|
||
if (optimalWidthLine < widthLine) {
|
||
this.widthCanvas = widthCanvas;
|
||
this.scaleX = scaleX;
|
||
this.scaleY = scaleY;
|
||
this.scaleZ = scaleZ;
|
||
|
||
this.aspectRatioX = aspectRatioX;
|
||
this.aspectRatioY = aspectRatioY;
|
||
this.aspectRatioZ = aspectRatioZ;
|
||
|
||
return;
|
||
}
|
||
|
||
this.aspectRatioX = widthLine / ((optimalWidthLine - newDepth) / kF);
|
||
this.scaleY = this.scaleY * kF;
|
||
this.scaleZ = this.scaleZ * kF;
|
||
|
||
this.widthCanvas = widthCanvas;
|
||
|
||
this._recalculateCameraDiff();
|
||
} else {
|
||
//рассчитываем параметры диаграммы при оптимальной ширине
|
||
this.widthCanvas = optimalWidth + (this.left + this.right);
|
||
this.calaculate3DProperties(null, null, true);
|
||
|
||
optimalWidthLine = this.depthPerspective * Math.sin(-this.angleOy) + ((this.widthCanvas - (this.left + this.right)) / this.aspectRatioX) / this.scaleX;
|
||
|
||
if (optimalWidthLine < widthLine) {
|
||
this.widthCanvas = widthCanvas;
|
||
this.scaleX = scaleX;
|
||
this.scaleY = scaleY;
|
||
this.scaleZ = scaleZ;
|
||
|
||
this.aspectRatioX = aspectRatioX;
|
||
this.aspectRatioY = aspectRatioY;
|
||
this.aspectRatioZ = aspectRatioZ;
|
||
|
||
return;
|
||
}
|
||
|
||
kF = optimalWidthLine / widthLine;
|
||
this.aspectRatioX = widthLine / ((optimalWidthLine - this.depthPerspective * Math.sin(-this.angleOy)) / kF);
|
||
this.scaleY = this.scaleY * kF;
|
||
this.scaleZ = this.scaleZ * kF;
|
||
|
||
this.widthCanvas = widthCanvas;
|
||
|
||
this._recalculateCameraDiff();
|
||
}
|
||
}
|
||
};
|
||
|
||
Processor3D.prototype._calculateScaleNStandard = function () {
|
||
let seriesProps = this.chartsDrawer.calculateFirstChartCountSeries();
|
||
let ptCount = seriesProps.points;
|
||
|
||
let widthLine = this.widthCanvas - (this.left + this.right);
|
||
let heightLine = this.heightCanvas - (this.top + this.bottom);
|
||
|
||
let trueDepth = Math.abs(this.depthPerspective * Math.sin(-this.angleOx));
|
||
let mustHeight = heightLine - trueDepth;
|
||
let mustWidth = this.chartsDrawer.calcProp.type === AscFormat.c_oChartTypes.HBar ? mustHeight * this.hPercent : mustHeight / this.hPercent;
|
||
|
||
let areaStackedKf = this.chartsDrawer.calcProp.type === AscFormat.c_oChartTypes.Area && this.chartsDrawer.calcProp.subType !== "normal" ? (ptCount / ((ptCount - 1))) : 1;
|
||
|
||
//без маштабирования
|
||
if (this.angleOy === 0) {
|
||
this.aspectRatioX = ((this.widthCanvas - (this.left + this.right)) / mustWidth) / areaStackedKf;
|
||
this.scaleX = 1;
|
||
this.scaleY = 1;
|
||
this.aspectRatioY = heightLine / mustHeight;
|
||
} else {
|
||
this.aspectRatioX = ((this.widthCanvas - (this.left + this.right)) / mustWidth) / areaStackedKf;
|
||
this.scaleX = 1;
|
||
this.scaleY = 1;
|
||
this.aspectRatioY = heightLine / mustHeight;
|
||
}
|
||
|
||
let optimalWidthLine = (widthLine / this.aspectRatioX) / this.scaleX;
|
||
|
||
|
||
if (optimalWidthLine < widthLine) {
|
||
return;
|
||
}
|
||
|
||
let kF = optimalWidthLine / (widthLine);
|
||
this.aspectRatioX = kF * this.aspectRatioX;
|
||
this.scaleY = this.scaleY * kF;
|
||
this.scaleZ = this.scaleZ * kF;
|
||
};
|
||
|
||
Processor3D.prototype._recalculateCameraDiff = function () {
|
||
this.cameraDiffX = 0;
|
||
this.cameraDiffY = 0;
|
||
this.cameraDiffZ = 0;
|
||
|
||
this._calculateCameraDiff();
|
||
};
|
||
|
||
Processor3D.prototype.calculateZPositionValAxis = function () {
|
||
let result = 0;
|
||
if (!this.view3D.getRAngAx()) {
|
||
result = this.orientationCatAx !== ORIENTATION_MIN_MAX ? this.depthPerspective : 0;
|
||
if (this.chartsDrawer.calcProp.type !== AscFormat.c_oChartTypes.HBar) {
|
||
let angleOyAbs = Math.abs(this.angleOy);
|
||
if ((angleOyAbs >= Math.PI / 2 && angleOyAbs < Math.PI) || (angleOyAbs >= 3 * Math.PI / 2 && angleOyAbs < 2 * Math.PI)) {
|
||
result = this.orientationCatAx !== ORIENTATION_MIN_MAX ? 0 : this.depthPerspective;
|
||
}
|
||
} else {
|
||
if (this.orientationCatAx !== ORIENTATION_MIN_MAX) {
|
||
result = Math.cos(this.angleOy) > 0 ? this.depthPerspective : 0;
|
||
} else {
|
||
result = Math.cos(this.angleOy) > 0 ? 0 : this.depthPerspective;
|
||
}
|
||
}
|
||
} else if (this.chartsDrawer.calcProp.type !== AscFormat.c_oChartTypes.HBar && this.orientationCatAx !== ORIENTATION_MIN_MAX && this.depthPerspective !== undefined) {
|
||
result = this.depthPerspective;
|
||
} else if (this.chartsDrawer.calcProp.type === AscFormat.c_oChartTypes.HBar && this.orientationCatAx !== ORIENTATION_MIN_MAX && this.depthPerspective !== undefined) {
|
||
//if(this.chartSpace.chart.plotArea.valAx && this.chartSpace.chart.plotArea.valAx.yPoints && this.chartSpace.chart.plotArea.catAx.posY === this.chartSpace.chart.plotArea.valAx.yPoints[0].pos)
|
||
result = this.depthPerspective;
|
||
}
|
||
|
||
return result;
|
||
};
|
||
|
||
Processor3D.prototype.calculateZPositionCatAxis = function () {
|
||
let result = 0;
|
||
if (!this.view3D.getRAngAx()) {
|
||
if (this.chartsDrawer.calcProp.type === AscFormat.c_oChartTypes.HBar && this.orientationValAx !== ORIENTATION_MIN_MAX) {
|
||
result = Math.cos(this.angleOy) > 0 ? this.depthPerspective : 0;
|
||
} else {
|
||
result = Math.cos(this.angleOy) > 0 ? 0 : this.depthPerspective;
|
||
}
|
||
} else if (this.chartsDrawer.calcProp.type !== AscFormat.c_oChartTypes.HBar && this.orientationValAx !== ORIENTATION_MIN_MAX && this.depthPerspective !== undefined) {
|
||
if (this.chartSpace.chart.plotArea.valAx && this.chartSpace.chart.plotArea.valAx.yPoints && this.chartSpace.chart.plotArea.catAx.posY ===
|
||
this.chartSpace.chart.plotArea.valAx.yPoints[0].pos) {
|
||
result = this.depthPerspective;
|
||
}
|
||
} else if (this.chartsDrawer.calcProp.type === AscFormat.c_oChartTypes.HBar && this.orientationValAx !== ORIENTATION_MIN_MAX && this.depthPerspective !== undefined) {
|
||
result = this.depthPerspective;
|
||
}
|
||
|
||
return result;
|
||
};
|
||
|
||
Processor3D.prototype.calculateXPositionSerAxis = function () {
|
||
if (!this.view3D.getRAngAx()) {
|
||
return Math.sin(this.angleOy) > 0;
|
||
}
|
||
};
|
||
|
||
Processor3D.prototype.calculateFloorPosition = function () {
|
||
let res, absOy;
|
||
|
||
if (this.view3D.getRAngAx()) {
|
||
if (this.chartsDrawer.calcProp.type === AscFormat.c_oChartTypes.HBar) {
|
||
absOy = Math.abs(this.angleOy);
|
||
res = c_oChartFloorPosition.Left;
|
||
if (absOy > Math.PI) {
|
||
res = c_oChartFloorPosition.Right;
|
||
}
|
||
} else {
|
||
res = c_oChartFloorPosition.Bottom;
|
||
if (this.angleOx > 0) {
|
||
res = c_oChartFloorPosition.None;
|
||
}
|
||
}
|
||
|
||
} else {
|
||
if (this.chartsDrawer.calcProp.type === AscFormat.c_oChartTypes.HBar) {
|
||
absOy = Math.abs(this.angleOy);
|
||
res = c_oChartFloorPosition.Left;
|
||
if (absOy > Math.PI) {
|
||
res = c_oChartFloorPosition.Right;
|
||
}
|
||
} else {
|
||
res = c_oChartFloorPosition.Bottom;
|
||
if (this.angleOx > 0) {
|
||
res = c_oChartFloorPosition.None;
|
||
}
|
||
}
|
||
}
|
||
|
||
return res;
|
||
};
|
||
|
||
//***functions for complete transformation point***
|
||
Processor3D.prototype.convertAndTurnPoint = function (x, y, z, isNScale, isNRotate, isNProject) {
|
||
let res = null;
|
||
|
||
if (this.view3D.getRAngAx()) {
|
||
res = this.convertAndTurnPointRAngAx(x, y, z);
|
||
} else {
|
||
res = this.convertAndTurnPointPerspective(x, y, z, isNScale, isNRotate, isNProject);
|
||
}
|
||
|
||
return res;
|
||
};
|
||
|
||
Processor3D.prototype.convertAndTurnPointRAngAx = function (x, y, z) {
|
||
let heightChart = this.heightCanvas - this.top - this.bottom;
|
||
|
||
let point3D = new Point3D(x, y, z, this);
|
||
this.scale(point3D);
|
||
|
||
//diff
|
||
let centerXDiff = heightChart / 2 + this.left / 2;
|
||
let centerYDiff = heightChart / 2 + this.top;
|
||
let centerZDiff = this.depthPerspective / 2;
|
||
|
||
point3D.offset(-centerXDiff, -centerYDiff, -centerZDiff);
|
||
|
||
//rotate
|
||
let matrixRotateAllAxis = this._shearXY();
|
||
point3D.multiplyPointOnMatrix1(matrixRotateAllAxis);
|
||
|
||
// diff camera for charts write into rect
|
||
point3D.offset(this.cameraDiffX, this.cameraDiffY, this.cameraDiffZ);
|
||
|
||
//undiff
|
||
let specialReverseDiff = this.widthCanvas / 2 + (this.left - this.right) / 2;
|
||
point3D.offset(specialReverseDiff, centerYDiff, centerZDiff);
|
||
|
||
return {x: point3D.x, y: point3D.y, z: z};
|
||
};
|
||
|
||
Processor3D.prototype.convertAndTurnPointPerspective = function (x, y, z, isNScale, isNRotate, isNProject) {
|
||
let point3D = new Point3D(x, y, z, this);
|
||
|
||
if (!isNScale) {
|
||
this.scale(point3D);
|
||
}
|
||
|
||
if (!isNRotate) {
|
||
this.rotatePerspective(point3D);
|
||
}
|
||
|
||
if (!isNProject) {
|
||
this.projectPerspective(point3D);
|
||
}
|
||
|
||
return {x: point3D.x, y: point3D.y, z: point3D.z};
|
||
};
|
||
|
||
Processor3D.prototype.scale = function (point3D) {
|
||
//aspectRatio
|
||
point3D.x = point3D.x / this.aspectRatioX;
|
||
point3D.y = point3D.y / this.aspectRatioY;
|
||
|
||
point3D.x = point3D.x / this.scaleX;
|
||
point3D.y = point3D.y / this.scaleY;
|
||
point3D.z = point3D.z / this.scaleZ;
|
||
};
|
||
|
||
Processor3D.prototype.rotatePerspective = function (point3D) {
|
||
//diff
|
||
point3D.offset((-this.widthCanvas / 2) / this.aspectRatioX, (-this.heightCanvas / 2) / this.aspectRatioY, 0);
|
||
//rotate
|
||
let matrixRotateAllAxis = this._getMatrixRotateAllAxis();
|
||
point3D.multiplyPointOnMatrix1(matrixRotateAllAxis);
|
||
|
||
point3D.offset((this.widthCanvas / 2) / this.aspectRatioX, (this.heightCanvas / 2) / this.aspectRatioY, 0);
|
||
};
|
||
|
||
Processor3D.prototype.projectPerspective = function (point3D) {
|
||
//diff
|
||
point3D.offset((-this.widthCanvas / 2) / this.aspectRatioX, (-this.heightCanvas / 2) / this.aspectRatioY /** aspectRatio*/, 0);
|
||
|
||
// diff camera for charts write into rect
|
||
point3D.offset(this.cameraDiffX, this.cameraDiffY, this.cameraDiffZ);
|
||
|
||
//project
|
||
let projectiveMatrix = this._getPerspectiveProjectionMatrix(1 / (this.rPerspective));
|
||
point3D.project(projectiveMatrix);
|
||
|
||
//undiff
|
||
let specialReverseDiffX = this.widthCanvas / 2 + (this.left - this.right) / 2;
|
||
let specialReverseDiffY = this.heightCanvas / 2 + (this.top - this.bottom) / 2;
|
||
point3D.offset(specialReverseDiffX, specialReverseDiffY, 0);
|
||
};
|
||
|
||
//functions for step transformation point
|
||
Processor3D.prototype.calculatePointManual = function (x, y, z, diffX, diffY, diffZ) {
|
||
diffX = diffX !== undefined ? diffX : this.cameraDiffX;
|
||
diffY = diffY !== undefined ? diffY : this.cameraDiffY;
|
||
diffZ = diffZ !== undefined ? diffZ : this.cameraDiffZ;
|
||
|
||
let diffAndScalePoints = this.diffAndScale(x, y, z);
|
||
let x11 = diffAndScalePoints.x;
|
||
let y11 = diffAndScalePoints.y;
|
||
let z11 = diffAndScalePoints.z;
|
||
|
||
|
||
let rotatePoints = this.rotate(x11, y11, z11);
|
||
let x111 = rotatePoints.x;
|
||
let y111 = rotatePoints.y;
|
||
let z111 = rotatePoints.z;
|
||
|
||
let x1111 = x111 + diffX;
|
||
let y1111 = y111 + diffY;
|
||
let z1111 = z111 + diffZ;
|
||
|
||
|
||
let projectPoints = this.project(x1111, y1111, z1111);
|
||
let x11111 = projectPoints.x;
|
||
let y11111 = projectPoints.y;
|
||
|
||
return {x: x11111, y: y11111};
|
||
};
|
||
|
||
Processor3D.prototype.diffAndScale = function (x, y, z) {
|
||
let aRX = this.aspectRatioX;
|
||
let aRY = this.aspectRatioY;
|
||
|
||
let w = this.widthCanvas;
|
||
let h = this.heightCanvas;
|
||
|
||
let x1 = x / aRX;
|
||
let x11 = x1 - (w / 2) / aRX;
|
||
|
||
let z11 = z;
|
||
|
||
let y1 = y / aRY;
|
||
let y11 = y1 - (h / 2) / aRY;
|
||
|
||
return {x: x11, y: y11, z: z11};
|
||
};
|
||
|
||
Processor3D.prototype.rotate = function (x11, y11, z11) {
|
||
let sinOY = Math.sin(-this.angleOy);
|
||
let cosOY = Math.cos(-this.angleOy);
|
||
let sinOX = Math.sin(-this.angleOx);
|
||
let cosOX = Math.cos(-this.angleOx);
|
||
|
||
let x111 = z11 * sinOY + x11 * cosOY;
|
||
let y111 = x11 * sinOX * sinOY + y11 * cosOX - z11 * sinOX * cosOY;
|
||
let z111 = -x11 * sinOY * cosOX + y11 * sinOX + z11 * (cosOY * cosOX);
|
||
|
||
return {x: x111, y: y111, z: z111};
|
||
};
|
||
|
||
Processor3D.prototype.project = function (x1111, y1111, z1111) {
|
||
let fov = 1 / this.rPerspective;
|
||
|
||
let w = this.widthCanvas;
|
||
let h = this.heightCanvas;
|
||
|
||
let x11111 = (fov * x1111) / (z1111 + fov) + w / 2;
|
||
let y11111 = (fov * y1111) / (z1111 + fov) + h / 2;
|
||
|
||
return {x: x11111, y: y11111};
|
||
};
|
||
|
||
//exception for pie charts
|
||
Processor3D.prototype.convertAndTurnPointForPie = function (x, y, z) {
|
||
let heightChart = this.heightCanvas - this.top - this.bottom;
|
||
|
||
let point3D = new Point3D(x, y, z, this);
|
||
|
||
//diff
|
||
let centerXDiff = heightChart / 2 + this.left / 2;
|
||
let centerYDiff = heightChart / 2 + this.top;
|
||
let centerZDiff = this.depthPerspective / 2;
|
||
|
||
|
||
point3D.offset(-centerXDiff, -centerYDiff, -centerZDiff);
|
||
|
||
//rotate
|
||
let matrixRotateAllAxis;
|
||
if (!this.view3D.getRAngAx()) {
|
||
matrixRotateAllAxis = this._getMatrixRotateAllAxis();
|
||
} else {
|
||
matrixRotateAllAxis = this._shearXY();
|
||
}
|
||
|
||
point3D.multiplyPointOnMatrix1(matrixRotateAllAxis);
|
||
|
||
// diff camera for charts write into rect
|
||
point3D.offset(this.cameraDiffX, this.cameraDiffY, this.cameraDiffZ);
|
||
|
||
//project
|
||
let projectionPoint = point3D;
|
||
if (!this.view3D.getRAngAx()) {
|
||
let projectiveMatrix = this._getPerspectiveProjectionMatrix(1 / (this.rPerspective));
|
||
projectionPoint = point3D.project(projectiveMatrix);
|
||
}
|
||
|
||
//undiff
|
||
let specialReverseDiff = this.widthCanvas / 2 + (this.left - this.right) / 2;
|
||
projectionPoint.offset(specialReverseDiff, centerYDiff, centerZDiff);
|
||
|
||
//console.log(" this.aspectRatioX: " + this.aspectRatioX + " this.aspectRatioY: " + this.aspectRatioY + " this.scaleX: " + this.scaleX + " this.scaleY: " + this.scaleY);
|
||
|
||
return {x: projectionPoint.x, y: projectionPoint.y};
|
||
};
|
||
|
||
Processor3D.prototype.calculatePropertiesForPieCharts = function () {
|
||
let sinAngleOx = Math.sin(-this.angleOx);
|
||
let cosAngleOx = Math.cos(-this.angleOx);
|
||
|
||
let widthCharts = this.widthCanvas - this.left - this.right;
|
||
let heightCharts = this.heightCanvas - this.bottom - this.top;
|
||
let radius1 = widthCharts / 2;
|
||
let radius2 = radius1 * sinAngleOx;
|
||
let depth = ((widthCharts + 4.89) / 8.37) * cosAngleOx;
|
||
|
||
if ((radius2 * 2 + depth) > heightCharts) {
|
||
let kF = (radius2 * 2 + depth) / heightCharts;
|
||
radius1 = radius1 / kF;
|
||
radius2 = radius2 / kF;
|
||
depth = depth / kF;
|
||
}
|
||
|
||
//ToDo временная правка для круговой диграммы с углом поворота 0 градусов
|
||
if (0 === radius2) {
|
||
radius2 = 1;
|
||
}
|
||
|
||
return {radius1: radius1, radius2: radius2, depth: depth};
|
||
};
|
||
|
||
|
||
//***functions for matrix transformation***
|
||
Processor3D.prototype._shearXY = function () {
|
||
if (null === this.matrixShearXY) {
|
||
this.matrixShearXY = new Matrix4D();
|
||
|
||
this.matrixShearXY.a31 = Math.sin(-this.angleOy);
|
||
this.matrixShearXY.a32 = Math.sin(this.angleOx);
|
||
this.matrixShearXY.a33 = 0;
|
||
this.matrixShearXY.a44 = 0;
|
||
}
|
||
|
||
return this.matrixShearXY;
|
||
};
|
||
Processor3D.prototype._shearXY2 = function () {
|
||
if (null === this.matrixShearXY) {
|
||
this.matrixShearXY = [[1, 0, 0, 0], [0, 1, 0, 0], [Math.sin(-this.angleOy), Math.sin(this.angleOx), 0, 0], [0, 0, 0, 0]];
|
||
}
|
||
return this.matrixShearXY;
|
||
};
|
||
|
||
Processor3D.prototype._getMatrixRotateAllAxis = function () {
|
||
let matrixRotateOY = this._getMatrixRotateOy();
|
||
let matrixRotateOX = this._getMatrixRotateOx();
|
||
|
||
/*result matrix
|
||
|
||
|cosOy 0 sinOy 0|
|
||
|sinOx * sinOy cosOx -sinOx * cosOy 0|
|
||
|-sinOy * cosOx sinOx cosOy * cosOx 0|
|
||
|-sinOy 0 (cosOy + 1) 1|*/
|
||
|
||
if (null === this.matrixRotateAllAxis) {
|
||
this.matrixRotateAllAxis = matrixRotateOY.multiply(matrixRotateOX);
|
||
}
|
||
|
||
return this.matrixRotateAllAxis;
|
||
};
|
||
|
||
Processor3D.prototype._getMatrixRotateOx = function () {
|
||
//todo array -> Float32Array ?
|
||
if (null === this.matrixRotateOx) {
|
||
this.matrixRotateOx =
|
||
new Matrix4D()/*[[1, 0, 0, 0], [0, Math.cos(-this.angleOx), Math.sin(-this.angleOx), 0], [0, - Math.sin(-this.angleOx), Math.cos(-this.angleOx), 1], [0, 0, 0, 1]]*/;
|
||
|
||
let cos = Math.cos(-this.angleOx);
|
||
let sin = Math.sin(-this.angleOx);
|
||
|
||
this.matrixRotateOx.a22 = cos;
|
||
this.matrixRotateOx.a23 = sin;
|
||
this.matrixRotateOx.a32 = -sin;
|
||
this.matrixRotateOx.a33 = cos;
|
||
this.matrixRotateOx.a34 = 1;
|
||
}
|
||
|
||
return this.matrixRotateOx;
|
||
};
|
||
|
||
Processor3D.prototype._getMatrixRotateOy = function () {
|
||
if (null === this.matrixRotateOy) {
|
||
this.matrixRotateOy =
|
||
new Matrix4D()/*[[Math.cos(-this.angleOy), 0, -Math.sin(-this.angleOy), 0], [0, 1, 0, 0], [Math.sin(-this.angleOy), 0, Math.cos(-this.angleOy), 1], [0, 0, 0, 1]]*/;
|
||
|
||
let cos = Math.cos(-this.angleOy);
|
||
let sin = Math.sin(-this.angleOy);
|
||
|
||
this.matrixRotateOy.a11 = cos;
|
||
this.matrixRotateOy.a13 = -sin;
|
||
this.matrixRotateOy.a31 = sin;
|
||
this.matrixRotateOy.a33 = cos;
|
||
this.matrixRotateOy.a34 = 1;
|
||
}
|
||
|
||
return this.matrixRotateOy;
|
||
};
|
||
|
||
Processor3D.prototype._getMatrixRotateOz = function () {
|
||
return [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 0, 1]];
|
||
};
|
||
|
||
Processor3D.prototype._getPerspectiveProjectionMatrix = function (fov) {
|
||
/*let zf = this.rPerspective + this.depthPerspective;
|
||
let zn = this.rPerspective;
|
||
let q = zf / (zf - zn);
|
||
return [[1 / Math.tan(this.rPerspective / 2), 0, 0, 0], [0, 1 / Math.tan(this.rPerspective / 2), 0, 0], [0, 0, q, 1], [0, 0, -q * zn, 0]];*/
|
||
//[[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1 / fov], [0, 0, 0, 1]]
|
||
if (null === this.projectMatrix) {
|
||
this.projectMatrix = new Matrix4D();
|
||
this.projectMatrix.a33 = 0;
|
||
this.projectMatrix.a34 = 1 / fov;
|
||
}
|
||
|
||
return this.projectMatrix;
|
||
};
|
||
|
||
Processor3D.prototype.correctPointsPosition = function (chartSpace) {
|
||
if (this.chartsDrawer.calcProp.type === AscFormat.c_oChartTypes.Pie) {
|
||
return;
|
||
}
|
||
|
||
let pxToMM = 1 / AscCommon.g_dKoef_pix_to_mm;
|
||
let t = this;
|
||
//коррективы для подписей
|
||
let xPoints = chartSpace.chart.plotArea && chartSpace.chart.plotArea.catAx ? chartSpace.chart.plotArea.catAx.xPoints : null;
|
||
if (!xPoints) {
|
||
xPoints = chartSpace.chart.plotArea && chartSpace.chart.plotArea.valAx ? chartSpace.chart.plotArea.valAx.xPoints : null;
|
||
}
|
||
|
||
let coordYAxisOx = chartSpace.chart.plotArea.catAx && chartSpace.chart.plotArea.catAx.posY;
|
||
if (!coordYAxisOx && chartSpace.chart.plotArea.valAx) {
|
||
coordYAxisOx = chartSpace.chart.plotArea.valAx.posY != undefined ? chartSpace.chart.plotArea.valAx.posY : chartSpace.chart.plotArea.valAx.posY;
|
||
}
|
||
|
||
let yPoints = chartSpace.chart.plotArea && chartSpace.chart.plotArea.valAx ? chartSpace.chart.plotArea.valAx.yPoints : null;
|
||
if (!yPoints) {
|
||
yPoints = chartSpace.chart.plotArea && chartSpace.chart.plotArea.catAx ? chartSpace.chart.plotArea.catAx.yPoints : null;
|
||
}
|
||
|
||
let coordXAxisOy;
|
||
if (chartSpace.chart.plotArea.catAx) {
|
||
coordXAxisOy = chartSpace.chart.plotArea.catAx.posX ? chartSpace.chart.plotArea.catAx.posX : chartSpace.chart.plotArea.catAx.xPos;
|
||
}
|
||
if (!coordXAxisOy && chartSpace.chart.plotArea.valAx) {
|
||
coordXAxisOy = chartSpace.chart.plotArea.valAx.posX != undefined ? chartSpace.chart.plotArea.valAx.posX : null;
|
||
}
|
||
|
||
let correctPointsOx = function () {
|
||
let z = t.calculateZPositionCatAxis();
|
||
let valCatAx = chartSpace.chart.plotArea.catAx;
|
||
if (!valCatAx.transformXPoints) {
|
||
valCatAx.transformXPoints = [];
|
||
}
|
||
|
||
for (let i = 0; i < xPoints.length; i++) {
|
||
let widthText = 0;
|
||
if (valCatAx && valCatAx.labels && t.orientationValAx !== ORIENTATION_MIN_MAX) {
|
||
widthText = valCatAx.labels.extY * pxToMM;
|
||
}
|
||
|
||
let point = t.convertAndTurnPoint(xPoints[i].pos * pxToMM, coordYAxisOx * pxToMM - widthText, z);
|
||
|
||
valCatAx.transformXPoints[i] = {x: point.x / pxToMM, y: point.y / pxToMM};
|
||
}
|
||
};
|
||
|
||
let correctPointsOxHBar = function () {
|
||
let z = t.calculateZPositionValAxis();
|
||
let valCatAx = chartSpace.chart.plotArea.valAx;
|
||
if (!valCatAx.transformXPoints) {
|
||
valCatAx.transformXPoints = [];
|
||
}
|
||
|
||
for (let i = 0; i < xPoints.length; i++) {
|
||
let widthText = 0;
|
||
if (t.chartsDrawer.calcProp.type === AscFormat.c_oChartTypes.HBar && valCatAx && valCatAx.labels && t.orientationCatAx !== ORIENTATION_MIN_MAX) {
|
||
widthText = valCatAx.labels.extY * pxToMM;
|
||
}
|
||
|
||
let point = t.convertAndTurnPoint(xPoints[i].pos * pxToMM, coordYAxisOx * pxToMM - widthText, z);
|
||
|
||
valCatAx.transformXPoints[i] = {x: point.x / pxToMM, y: point.y / pxToMM};
|
||
}
|
||
};
|
||
|
||
let correctPointsOy = function () {
|
||
let zPosition = t.calculateZPositionValAxis();
|
||
let valCatAx = chartSpace.chart.plotArea.valAx;
|
||
|
||
if (!valCatAx.transformYPoints) {
|
||
valCatAx.transformYPoints = [];
|
||
}
|
||
|
||
for (let i = 0; i < yPoints.length; i++) {
|
||
let point = t.convertAndTurnPoint(coordXAxisOy * pxToMM, yPoints[i].pos * (pxToMM), zPosition);
|
||
|
||
//TODO значения высчитать
|
||
let widthText = 5;
|
||
if (valCatAx && valCatAx.labels) {
|
||
widthText = valCatAx.labels.extX * pxToMM;
|
||
}
|
||
|
||
if (t.orientationCatAx !== ORIENTATION_MIN_MAX) {
|
||
widthText = 0;
|
||
}
|
||
|
||
let diffXText = 0;
|
||
let angleOyAbs = Math.abs(t.angleOy);
|
||
if (!t.view3D.getRAngAx() && (angleOyAbs >= Math.PI / 2 && angleOyAbs < 3 * Math.PI / 2)) {
|
||
diffXText = -diffXText;
|
||
}
|
||
|
||
valCatAx.transformYPoints[i] = {
|
||
x: (point.x - (diffXText + widthText)) / pxToMM, y: point.y / pxToMM
|
||
};
|
||
}
|
||
};
|
||
|
||
let correctPointsOyHBar = function () {
|
||
let zPosition = t.calculateZPositionCatAxis();
|
||
let valCatAx = chartSpace.chart.plotArea.catAx;
|
||
if (!valCatAx.transformYPoints) {
|
||
valCatAx.transformYPoints = [];
|
||
}
|
||
|
||
for (let i = 0; i < yPoints.length; i++) {
|
||
let point = t.convertAndTurnPoint(coordXAxisOy * pxToMM, yPoints[i].pos * (pxToMM), zPosition);
|
||
|
||
//TODO значения высчитать
|
||
let widthText = 0;
|
||
if (valCatAx && valCatAx.labels) {
|
||
widthText = valCatAx.labels.extX * pxToMM;
|
||
}
|
||
|
||
if (t.orientationValAx !== ORIENTATION_MIN_MAX) {
|
||
widthText -= 10;
|
||
} else {
|
||
widthText += 5;
|
||
}
|
||
|
||
valCatAx.transformYPoints[i] = {x: (point.x - widthText) / pxToMM, y: point.y / pxToMM};
|
||
}
|
||
};
|
||
|
||
|
||
if (xPoints) {
|
||
if (this.chartsDrawer.calcProp.type !== AscFormat.c_oChartTypes.HBar) {
|
||
correctPointsOx(xPoints);
|
||
} else {
|
||
correctPointsOxHBar(xPoints);
|
||
}
|
||
}
|
||
|
||
if (yPoints) {
|
||
if (this.chartsDrawer.calcProp.type !== AscFormat.c_oChartTypes.HBar) {
|
||
correctPointsOy(yPoints);
|
||
} else {
|
||
correctPointsOyHBar(yPoints);
|
||
}
|
||
}
|
||
};
|
||
|
||
Processor3D.prototype._calculatePerspective = function (view3D) {
|
||
let heightLine = this.heightCanvas - (this.top + this.bottom);
|
||
|
||
let perspective = view3D && view3D.perspective ? view3D.perspective : global3DPersperctive;
|
||
if (view3D && 0 === view3D.perspective && this.chartsDrawer.calcProp.type === AscFormat.c_oChartTypes.Surface) {
|
||
perspective = 1;
|
||
}
|
||
|
||
let alpha = perspective / 4;//в xml проиходит двойной угол(в параметрах ms стоит 40, приходит в xml 80)
|
||
//TODO this.top - this.bottom пересмотреть
|
||
let catt = ((heightLine / 2 + (Math.abs(this.top - this.bottom)))) / Math.tan((alpha / 360) * (Math.PI * 2));
|
||
let rPerspective;
|
||
if (catt === 0) {
|
||
rPerspective = 0;
|
||
} else {
|
||
rPerspective = 1 / catt;
|
||
}
|
||
|
||
this.rPerspective = rPerspective;
|
||
};
|
||
|
||
Processor3D.prototype._calculateDepth = function () {
|
||
let widthOriginalChart = this.widthCanvas - (this.left + this.right);
|
||
let heightOriginalChart = this.heightCanvas - (this.top + this.bottom);
|
||
let subType = this.chartsDrawer.calcProp.subType;
|
||
let type = this.chartsDrawer.calcProp.type;
|
||
let defaultOverlap = (subType === "stacked" || subType === "stackedPer" || subType === "standard" || type === AscFormat.c_oChartTypes.Line || type ===
|
||
AscFormat.c_oChartTypes.Area || type === AscFormat.c_oChartTypes.Surface) ? 100 : 0;
|
||
let overlap = AscFormat.isRealNumber(this.chartSpace.chart.plotArea.chart.overlap) ? (this.chartSpace.chart.plotArea.chart.overlap / 100) : (defaultOverlap / 100);
|
||
let gapWidth = this.chartSpace.chart.plotArea.chart.gapWidth != null ? (this.chartSpace.chart.plotArea.chart.gapWidth / 100) : (150 / 100);
|
||
let gapDepth = this.chartSpace.chart.plotArea.chart.gapDepth != null ? (this.chartSpace.chart.plotArea.chart.gapDepth / 100) :
|
||
type === AscFormat.c_oChartTypes.Area && subType !== "normal" ? 1 : (150 / 100);
|
||
|
||
let seriesProps = this.chartsDrawer.calculateFirstChartCountSeries();
|
||
let seriesCount = seriesProps.series;
|
||
let ptCount = seriesProps.points;
|
||
|
||
let sinOx = Math.abs(Math.sin(-this.angleOx));
|
||
let sinOy = Math.sin(-this.angleOy);
|
||
let hPercent = type === AscFormat.c_oChartTypes.HBar ? 1 : this.hPercent;
|
||
let depthPercent = this._getDepthPercent();
|
||
let t = this;
|
||
|
||
let areaStackedKf = (type === AscFormat.c_oChartTypes.Area && subType !== "normal") || type === AscFormat.c_oChartTypes.Surface ? (ptCount / (2 * (ptCount - 1))) : 1;
|
||
|
||
let depth = 0;
|
||
let chartWidth = 0;
|
||
|
||
let standardType = false;
|
||
if (subType === "standard" || type === AscFormat.c_oChartTypes.Line || (type === AscFormat.c_oChartTypes.Area && subType === "normal") ||
|
||
(type === AscFormat.c_oChartTypes.Surface)) {
|
||
standardType = true;
|
||
}
|
||
|
||
let heightHPercent = heightOriginalChart / hPercent;
|
||
let angleOxKf;
|
||
if (!standardType) {
|
||
let widthOneBar = ((heightHPercent / seriesCount) / (ptCount - (ptCount - 1) * (overlap) + gapWidth)) * sinOy;
|
||
let a, b;
|
||
|
||
if (this.angleOx === 0 && this.angleOy === 0)//withoutAngleNoAuto + withoutAngleAuto
|
||
{
|
||
chartWidth = widthOneBar + heightHPercent;
|
||
} else if (this.angleOx !== 0)//AngleOYNoAut + AngleOYNoAutPerHeight + (ANGLEOX+ANGLEOY) + AngleOYOXNoAut + ANGLEOXANGLEOYHPerDPer(ANGLEOX+ANGLEOY HPercent)
|
||
{
|
||
//если выставить ширину 255 будет так же, как и в документе с расчётами
|
||
b = (seriesCount - (seriesCount - 1) * overlap + gapWidth);
|
||
a = (depthPercent / (ptCount * b)) / hPercent;
|
||
let width = heightOriginalChart * areaStackedKf;
|
||
depth = (width * a + gapDepth * width * a) / (1 / sinOx + (gapDepth) * a + a);
|
||
|
||
chartWidth = heightHPercent - depth;
|
||
} else if (this.angleOy !== 0)//angleOxNoAuto
|
||
{
|
||
//если выставить ширину = 321.25 будет так же, как и в документе с расчётам
|
||
//TODO глубина с некоторыми графиками имеет различия, пересчитать!
|
||
let widthChart = (widthOriginalChart / t.aspectRatioX) / t.specialStandardScaleX;
|
||
|
||
b = (seriesCount - (seriesCount - 1) * overlap + gapWidth);
|
||
if (subType === "standard" || type === AscFormat.c_oChartTypes.Line || type === AscFormat.c_oChartTypes.Area || type === AscFormat.c_oChartTypes.Surface) {
|
||
b = b / seriesCount;
|
||
}
|
||
|
||
angleOxKf = sinOx === 0 ? 1 : sinOx;
|
||
a = depthPercent / (ptCount * b);
|
||
depth = (widthChart * a + gapDepth * widthChart * a) / (1 / angleOxKf + (gapDepth) * a + a);
|
||
|
||
depth = depth / angleOxKf;
|
||
}
|
||
} else//allStandardDepth
|
||
{
|
||
angleOxKf = sinOx === 0 ? 0 : sinOx;
|
||
|
||
if (type === AscFormat.c_oChartTypes.Area) {
|
||
depth =
|
||
(depthPercent / (angleOxKf * depthPercent + ((ptCount + (Math.floor((seriesCount - ptCount) / 2 - 0.5))) / seriesCount * hPercent))) * (heightOriginalChart);
|
||
} else {
|
||
depth = (depthPercent / (angleOxKf * depthPercent + ((ptCount + (Math.floor((seriesCount - ptCount) / 2))) / seriesCount * hPercent))) * (heightOriginalChart);
|
||
}
|
||
|
||
if ((this.angleOx !== 0)) {
|
||
depth = depth * Math.sin(-this.angleOx);
|
||
}
|
||
}
|
||
|
||
return sinOx !== 0 ? Math.abs(depth / sinOx) : Math.abs(depth);
|
||
};
|
||
|
||
Processor3D.prototype._calculateDepthPerspective = function () {
|
||
let widthCanvas = this.widthCanvas;
|
||
let widthOriginalChart = widthCanvas - (this.left + this.right);
|
||
|
||
let aspectRatio = this.aspectRatioX / (this.specialStandardScaleX);
|
||
let widthChart = widthOriginalChart / aspectRatio;
|
||
widthChart = widthChart / this.scaleX;
|
||
|
||
let countSeries = this.chartsDrawer.calculateFirstChartCountSeries();
|
||
let seriesCount = countSeries.series;
|
||
let ptCount = countSeries.points;
|
||
|
||
let width = widthChart / ptCount;
|
||
|
||
let isNormalArea = (this.chartsDrawer.calcProp.subType === "normal" && this.chartsDrawer.calcProp.type === AscFormat.c_oChartTypes.Area) ||
|
||
this.chartsDrawer.calcProp.type === AscFormat.c_oChartTypes.Surface;
|
||
|
||
let defaultOverlap = (this.chartsDrawer.calcProp.subType === "stacked" || this.chartsDrawer.calcProp.subType === "stackedPer" || this.chartsDrawer.calcProp.subType ===
|
||
"standard" || this.chartsDrawer.calcProp.type === AscFormat.c_oChartTypes.Line || isNormalArea) ? 100 : 0;
|
||
let overlap = AscFormat.isRealNumber(this.chartSpace.chart.plotArea.chart.overlap) ? (this.chartSpace.chart.plotArea.chart.overlap / 100) : (defaultOverlap / 100);
|
||
|
||
let gapWidth = this.chartSpace.chart.plotArea.chart.gapWidth != null ? (this.chartSpace.chart.plotArea.chart.gapWidth / 100) : (150 / 100);
|
||
let gapDepth = this.chartSpace.chart.plotArea.chart.gapDepth != null ? (this.chartSpace.chart.plotArea.chart.gapDepth / 100) : (150 / 100);
|
||
|
||
if (AscFormat.c_oChartTypes.Area === this.chartsDrawer.calcProp.type || AscFormat.c_oChartTypes.Surface === this.chartsDrawer.calcProp.type) {
|
||
gapWidth = 0;
|
||
gapDepth = 0;
|
||
}
|
||
|
||
let baseDepth = width / (seriesCount - (seriesCount - 1) * overlap + gapWidth);
|
||
if (this.chartsDrawer.calcProp.subType === "standard" || this.chartsDrawer.calcProp.type === AscFormat.c_oChartTypes.Line || isNormalArea) {
|
||
baseDepth = (width / (seriesCount - (seriesCount - 1) * overlap + gapWidth)) * seriesCount;
|
||
}
|
||
|
||
let basePercent = this._getDepthPercent();
|
||
let depth = baseDepth * basePercent;
|
||
depth = depth + depth * gapDepth;
|
||
|
||
if (this.chartsDrawer.calcProp.type === AscFormat.c_oChartTypes.HBar && this.hPercent !== null) {
|
||
depth = this.hPercent * depth;
|
||
}
|
||
|
||
//TODO глубина в некоторых случаях отличается(тип Standard)
|
||
if (this.chartsDrawer.calcProp.subType === "standard" || this.chartsDrawer.calcProp.type === AscFormat.c_oChartTypes.Line || isNormalArea) {
|
||
let b = 1 / seriesCount;
|
||
|
||
let sinOx = Math.sin(-this.angleOx);
|
||
let angleOxKf = 1;
|
||
let a = basePercent / (ptCount * b);
|
||
depth = (widthChart * a + widthChart * a) / (1 / angleOxKf + a);
|
||
|
||
depth = depth / angleOxKf;
|
||
}
|
||
|
||
return depth;
|
||
};
|
||
|
||
Processor3D.prototype._calcSpecialStandardScaleX = function () {
|
||
let type = this.chartsDrawer.calcProp.type;
|
||
let subType = this.chartsDrawer.calcProp.subType;
|
||
if (!(subType === "standard" || type === AscFormat.c_oChartTypes.Line || (type === AscFormat.c_oChartTypes.Area && subType === "normal") || type ===
|
||
AscFormat.c_oChartTypes.Surface)) {
|
||
return;
|
||
}
|
||
|
||
let countSeries = this.chartsDrawer.calculateFirstChartCountSeries();
|
||
let seriesCount = countSeries.series;
|
||
let ptCount = countSeries.points;
|
||
|
||
//calculate width in 3d standard charts with rAngAx
|
||
let n = Math.floor((seriesCount + ptCount) / 2);
|
||
let kf = ptCount / n;
|
||
|
||
this.specialStandardScaleX = 1 / kf;
|
||
};
|
||
|
||
Processor3D.prototype._calculateScaleFromDepth = function (/*isSkip*/) {
|
||
//***Calculate scaleY***
|
||
if (this.view3D.getRAngAx() && this.aspectRatioY === 1) {
|
||
let heightCanvas = this.heightCanvas;
|
||
let heightChart = heightCanvas - this.top - this.bottom;
|
||
|
||
this.scaleY = heightChart / (-this.depthPerspective * Math.sin(Math.abs(this.angleOx)) + heightChart);
|
||
|
||
let subType = this.chartsDrawer.calcProp.subType;
|
||
let newDepth, newWidth;
|
||
if (!(subType === "standard" || this.chartsDrawer.calcProp.type === AscFormat.c_oChartTypes.Line || this.chartsDrawer.calcProp.type ===
|
||
AscFormat.c_oChartTypes.Surface || (this.chartsDrawer.calcProp.type === AscFormat.c_oChartTypes.Area && subType === "normal"))) {
|
||
newDepth = this.depthPerspective * Math.sin(-this.angleOx);
|
||
newWidth = heightChart - newDepth;
|
||
this.scaleX = heightChart / newWidth;
|
||
}
|
||
}
|
||
};
|
||
|
||
Processor3D.prototype._calculateCameraDiff = function (/*isSkip*/) {
|
||
//глубина по OZ
|
||
let perspectiveDepth = this.depthPerspective;
|
||
|
||
let widthCanvas = this.widthCanvas;
|
||
let originalWidthChart = widthCanvas - this.left - this.right;
|
||
|
||
let heightCanvas = this.heightCanvas;
|
||
let heightChart = heightCanvas - this.top - this.bottom;
|
||
|
||
//add test points for parallelepiped rect
|
||
let points = [];
|
||
let faces = [];
|
||
|
||
/*if(AscFormat.c_oChartTypes.Pie === this.chartsDrawer.calcProp.type)
|
||
{
|
||
points.push(new Point3D(this.left + originalWidthChart / 2, this.top, perspectiveDepth, this));
|
||
points.push(new Point3D(this.left, this.top, perspectiveDepth / 2, this));
|
||
points.push(new Point3D(this.left + originalWidthChart, this.top, perspectiveDepth / 2, this));
|
||
points.push(new Point3D(this.left + originalWidthChart / 2, this.top, 0, this));
|
||
|
||
points.push(new Point3D(this.left + originalWidthChart / 2, this.top + heightChart, perspectiveDepth, this));
|
||
points.push(new Point3D(this.left, this.top + heightChart, perspectiveDepth / 2, this));
|
||
points.push(new Point3D(this.left + originalWidthChart, this.top + heightChart, perspectiveDepth / 2, this));
|
||
points.push(new Point3D(this.left + originalWidthChart / 2, this.top + heightChart, 0, this));
|
||
}
|
||
else
|
||
{*/
|
||
points.push(new Point3D(this.left, this.top, perspectiveDepth, this));
|
||
points.push(new Point3D(this.left, heightChart + this.top, perspectiveDepth, this));
|
||
points.push(new Point3D(originalWidthChart + this.left, heightChart + this.top, perspectiveDepth, this));
|
||
points.push(new Point3D(originalWidthChart + this.left, this.top, perspectiveDepth, this));
|
||
points.push(new Point3D(originalWidthChart + this.left, this.top, 0, this));
|
||
points.push(new Point3D(originalWidthChart + this.left, heightChart + this.top, 0, this));
|
||
points.push(new Point3D(this.left, heightChart + this.top, 0, this));
|
||
points.push(new Point3D(this.left, this.top, 0, this));
|
||
//}
|
||
|
||
faces.push([0, 1, 2, 3]);
|
||
faces.push([2, 5, 4, 3]);
|
||
faces.push([1, 6, 7, 0]);
|
||
faces.push([6, 5, 4, 7]);
|
||
faces.push([7, 4, 3, 0]);
|
||
faces.push([1, 6, 2, 5]);
|
||
|
||
|
||
//***Calculate cameraDiffZ***
|
||
if (!this.view3D.getRAngAx()) {
|
||
//быстрая функция поиска сдвигов камеры
|
||
//console.time("sdf");
|
||
this._calculateCameraDiffZX(points, faces);
|
||
//console.timeEnd("sdf");
|
||
}
|
||
|
||
//***Calculate cameraDiffX***
|
||
if (this.view3D.getRAngAx()) {
|
||
let minMaxOx = this._getMinMaxOx(points, faces);
|
||
this._calculateCameraDiffX(minMaxOx);
|
||
|
||
//***Calculate cameraDiffY***
|
||
let minMaxOy = this._getMinMaxOy(points, faces);
|
||
this._calculateCameraDiffY(minMaxOy.top, minMaxOy.bottom);
|
||
}
|
||
};
|
||
|
||
Processor3D.prototype._calculateCameraDiffZX = function (newPoints) {
|
||
let heightChart = this.heightCanvas - this.top - this.bottom;
|
||
let widthOriginalChart = this.widthCanvas - this.left - this.right;
|
||
let heightOriginalChart = heightChart;
|
||
|
||
let minX = null;
|
||
let maxX = null;
|
||
let minZ = null;
|
||
|
||
let aspectRatio = (widthOriginalChart) / (heightOriginalChart);
|
||
|
||
|
||
for (let i = 0; i < newPoints.length; i++) {
|
||
let point3D = new Point3D(newPoints[i].x, newPoints[i].y, newPoints[i].z, this);
|
||
|
||
point3D.scale(aspectRatio, 1, 1);
|
||
point3D.offset((-this.widthCanvas / 2) / aspectRatio, (-this.heightCanvas / 2), 0);
|
||
|
||
//rotate
|
||
let matrixRotateAllAxis = this._getMatrixRotateAllAxis();
|
||
point3D.multiplyPointOnMatrix1(matrixRotateAllAxis);
|
||
|
||
|
||
if (minZ === null || point3D.z < minZ) {
|
||
minZ = point3D.z;
|
||
}
|
||
|
||
if (minX === null || point3D.x < minX) {
|
||
minX = point3D.x;
|
||
}
|
||
|
||
if (maxX === null || point3D.x > maxX) {
|
||
maxX = point3D.x;
|
||
}
|
||
}
|
||
|
||
//get min and max point's and diffX
|
||
/*if(-t.angleOx === 0)
|
||
{
|
||
let minMaxOx = this._getMinMaxOxPoints(newPoints, minZ);
|
||
this.cameraDiffZ = - minZ;
|
||
this.cameraDiffX = - minMaxOx.diffX;
|
||
|
||
let x111 = this.convertAndTurnPoint(minMaxOx.tempX1, minMaxOx.tempY1, minMaxOx.tempZ1);
|
||
let x222 = this.convertAndTurnPoint(minMaxOx.tempX2, minMaxOx.tempY2, minMaxOx.tempZ2);
|
||
|
||
if(Math.abs(x222.x - x111.x) > widthOriginalChart)
|
||
{
|
||
let correctOffset;
|
||
if(x222.x > x111.x)
|
||
{
|
||
correctOffset = this._correctZPosition4(minMaxOx.tempX1, minMaxOx.tempX2, minMaxOx.tempZ1, minMaxOx.tempZ2, minZ, minMaxOx.tempY1, minMaxOx.tempY2);
|
||
}
|
||
else
|
||
{
|
||
correctOffset = this._correctZPosition4(minMaxOx.tempX1, minMaxOx.tempX2, minMaxOx.tempZ1, minMaxOx.tempZ2, minZ, minMaxOx.tempY1, minMaxOx.tempY2);
|
||
}
|
||
|
||
this.cameraDiffZ = Math.abs(correctOffset.minZ);
|
||
this.cameraDiffX = correctOffset.diffX;
|
||
}
|
||
}
|
||
else if(-t.angleOy === 0 && -t.angleOx !== 0)
|
||
{
|
||
let minMaxOy = this._getMinMaxOyPoints(newPoints, minZ);
|
||
this.cameraDiffZ = - minZ;
|
||
this.cameraDiffY = -minMaxOy.diffY;
|
||
|
||
let y111 = this.convertAndTurnPoint(minMaxOy.tempX1, minMaxOy.tempY1, minMaxOy.tempZ1);
|
||
let y222 = this.convertAndTurnPoint(minMaxOy.tempX2, minMaxOy.tempY2, minMaxOy.tempZ2);
|
||
|
||
if(Math.abs(y111.y - y222.y) < heightOriginalChart)
|
||
{
|
||
let minMaxOx = this._getMinMaxOxPoints(newPoints, minZ);
|
||
let x111 = this.convertAndTurnPoint(minMaxOx.tempX1, minMaxOx.tempY1, minMaxOx.tempZ1);
|
||
let x222 = this.convertAndTurnPoint(minMaxOx.tempX2, minMaxOx.tempY2, minMaxOx.tempZ2);
|
||
|
||
let correctOffset;
|
||
if(x222.x > x111.x)
|
||
{
|
||
correctOffset = this._correctZPosition4(minMaxOx.tempX1, minMaxOx.tempX2, minMaxOx.tempZ1, minMaxOx.tempZ2, minZ, minMaxOx.tempY1, minMaxOx.tempY2);
|
||
}
|
||
else
|
||
{
|
||
correctOffset = this._correctZPosition4(minMaxOx.tempX1, minMaxOx.tempX2, minMaxOx.tempZ1, minMaxOx.tempZ2, minZ, minMaxOx.tempY1, minMaxOx.tempY2);
|
||
}
|
||
|
||
this.cameraDiffZ = Math.abs(correctOffset.minZ);
|
||
this.cameraDiffX = correctOffset.diffX;
|
||
|
||
|
||
let minMaxOy = this._getMinMaxOyPoints(newPoints, 0);
|
||
//this.cameraDiffZ = - minZ;
|
||
this.cameraDiffY = -minMaxOy.diffY;
|
||
}
|
||
}*/
|
||
/*else if(-t.angleOy !== 0 && -t.angleOx !== 0)
|
||
{
|
||
let minMaxOx = this._getMinMaxOxPoints(newPoints, minZ);
|
||
let x111 = this.convertAndTurnPoint(minMaxOx.tempX1, minMaxOx.tempY1, minMaxOx.tempZ1);
|
||
let x222 = this.convertAndTurnPoint(minMaxOx.tempX2, minMaxOx.tempY2, minMaxOx.tempZ2);
|
||
|
||
let correctOffset;
|
||
if(x222.x > x111.x)
|
||
{
|
||
correctOffset = this._correctZPosition4(minMaxOx.tempX1, minMaxOx.tempX2, minMaxOx.tempZ1, minMaxOx.tempZ2, minZ, minMaxOx.tempY1, minMaxOx.tempY2);
|
||
}
|
||
else
|
||
{
|
||
correctOffset = this._correctZPosition4(minMaxOx.tempX2, minMaxOx.tempX1, minMaxOx.tempZ2, minMaxOx.tempZ1, minZ, minMaxOx.tempY2, minMaxOx.tempY1);
|
||
}
|
||
|
||
this.cameraDiffZ = correctOffset.minZ;
|
||
this.cameraDiffX = correctOffset.diffX;
|
||
|
||
let minMaxOy = this._getMinMaxOyPoints2(newPoints, this.cameraDiffZ);
|
||
this.cameraDiffY = minMaxOy.diffY;
|
||
|
||
console.log(" tempX1: " + minMaxOy.tempX1 + " tempX2: " + minMaxOy.tempX2 + " tempY1: " + minMaxOy.tempY1 + " tempY2: " + minMaxOy.tempY2 + " tempZ1: " + minMaxOy.tempZ1 + " tempZ2: " + minMaxOy.tempZ2);
|
||
|
||
let y111 = this.convertAndTurnPoint(minMaxOy.tempX1, minMaxOy.tempY1, minMaxOy.tempZ1);
|
||
let y222 = this.convertAndTurnPoint(minMaxOy.tempX2, minMaxOy.tempY2, minMaxOy.tempZ2);
|
||
|
||
if(y111.y < this.top || y222.y > this.top + heightOriginalChart)
|
||
{
|
||
//correctOffset = this._correctZPositionOY(minMaxOy.tempX1, minMaxOy.tempX2, minMaxOy.tempZ1, minMaxOy.tempZ2, minZ, minMaxOy.tempY1, minMaxOy.tempY2);
|
||
this.cameraDiffZ = minMaxOy.diffZ;
|
||
//this.cameraDiffY = minMaxOy.diffY;
|
||
|
||
let minMaxOx = this._getMinMaxOxPoints(newPoints, -this.cameraDiffZ);
|
||
//correctOffset = this._correctZPosition4(minMaxOx.tempX1, minMaxOx.tempX2, minMaxOx.tempZ1, minMaxOx.tempZ2, -this.cameraDiffZ, minMaxOx.tempY1, minMaxOx.tempY2);
|
||
this.cameraDiffX = -minMaxOx.diffX;
|
||
}
|
||
|
||
|
||
|
||
//TODO пока включаю для поворотов по OX + по OY checkOutSideArea(медленная функция), затем нужно переделать, используя закомментированный код сверху
|
||
this.cameraDiffZ = -minZ;
|
||
//this.cameraDiffX = -minMaxOx.diffX;
|
||
this.checkOutSideArea(newPoints);
|
||
}*/
|
||
|
||
//TODO пока включаю для ВСЕГО checkOutSideArea(медленная функция), затем нужно переделать, используя закомментированный код сверху
|
||
this.cameraDiffZ = -minZ;
|
||
this.checkOutSideArea2(newPoints);
|
||
|
||
};
|
||
|
||
//TODO если будут проблемы при маштабировании, вернуть функцию checkOutSideArea2 вместо checkOutSideArea
|
||
Processor3D.prototype.checkOutSideArea2 = function (newPoints) {
|
||
let i = 0;
|
||
let maxI = 1000;
|
||
let t = this;
|
||
|
||
let heightChart = this.heightCanvas - this.top - this.bottom;
|
||
let widthChart = this.widthCanvas - this.left - this.right;
|
||
|
||
let calculateZ = function (step) {
|
||
let minMaxOx = t._getMinMaxOxPoints(newPoints, -t.cameraDiffZ);
|
||
t.cameraDiffX = -minMaxOx.diffX;
|
||
let x111 = t.convertAndTurnPoint(minMaxOx.tempX1, minMaxOx.tempY1, minMaxOx.tempZ1);
|
||
let x222 = t.convertAndTurnPoint(minMaxOx.tempX2, minMaxOx.tempY2, minMaxOx.tempZ2);
|
||
|
||
let diffX = Math.abs(x222.x - x111.x);
|
||
|
||
let minMaxOy = t._getMinMaxOyPoints(newPoints, t.cameraDiffZ);
|
||
t.cameraDiffY = -minMaxOy.diffY;
|
||
let y111 = t.convertAndTurnPoint(minMaxOy.tempX1, minMaxOy.tempY1, minMaxOy.tempZ1);
|
||
let y222 = t.convertAndTurnPoint(minMaxOy.tempX2, minMaxOy.tempY2, minMaxOy.tempZ2);
|
||
|
||
let diffY = Math.abs(y222.y - y111.y);
|
||
|
||
if (diffX < widthChart && diffY < heightChart)//if size less then width or height
|
||
{
|
||
while (diffX < widthChart && diffY < heightChart) {
|
||
t.cameraDiffZ -= step;
|
||
i++;
|
||
minMaxOx = t._getMinMaxOxPoints(newPoints, -t.cameraDiffZ);
|
||
t.cameraDiffX = -minMaxOx.diffX;
|
||
|
||
x111 = t.convertAndTurnPoint(minMaxOx.tempX1, minMaxOx.tempY1, minMaxOx.tempZ1);
|
||
x222 = t.convertAndTurnPoint(minMaxOx.tempX2, minMaxOx.tempY2, minMaxOx.tempZ2);
|
||
diffX = Math.abs(x222.x - x111.x);
|
||
|
||
minMaxOy = t._getMinMaxOyPoints(newPoints, t.cameraDiffZ);
|
||
t.cameraDiffY = -minMaxOy.diffY;
|
||
y111 = t.convertAndTurnPoint(minMaxOy.tempX1, minMaxOy.tempY1, minMaxOy.tempZ1);
|
||
y222 = t.convertAndTurnPoint(minMaxOy.tempX2, minMaxOy.tempY2, minMaxOy.tempZ2);
|
||
diffY = Math.abs(y222.y - y111.y);
|
||
|
||
if (i > maxI) {
|
||
break;
|
||
}
|
||
}
|
||
} else if (diffX > widthChart || diffY > heightChart)//if size more then width or height
|
||
{
|
||
while (diffX > widthChart || diffY > heightChart) {
|
||
t.cameraDiffZ += step;
|
||
i++;
|
||
minMaxOx = t._getMinMaxOxPoints(newPoints, -t.cameraDiffZ);
|
||
t.cameraDiffX = -minMaxOx.diffX;
|
||
|
||
x111 = t.convertAndTurnPoint(minMaxOx.tempX1, minMaxOx.tempY1, minMaxOx.tempZ1);
|
||
x222 = t.convertAndTurnPoint(minMaxOx.tempX2, minMaxOx.tempY2, minMaxOx.tempZ2);
|
||
diffX = Math.abs(x222.x - x111.x);
|
||
|
||
minMaxOy = t._getMinMaxOyPoints(newPoints, t.cameraDiffZ);
|
||
t.cameraDiffY = -minMaxOy.diffY;
|
||
y111 = t.convertAndTurnPoint(minMaxOy.tempX1, minMaxOy.tempY1, minMaxOy.tempZ1);
|
||
y222 = t.convertAndTurnPoint(minMaxOy.tempX2, minMaxOy.tempY2, minMaxOy.tempZ2);
|
||
diffY = Math.abs(y222.y - y111.y);
|
||
|
||
if (i > maxI) {
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
};
|
||
|
||
calculateZ(100);
|
||
calculateZ(10);
|
||
calculateZ(1);
|
||
};
|
||
|
||
Processor3D.prototype.checkOutSideArea = function (newPoints) {
|
||
let t = this;
|
||
|
||
let heightChart = this.heightCanvas - this.top - this.bottom;
|
||
let widthChart = this.widthCanvas - this.left - this.right;
|
||
let DELTA = 3;
|
||
let maxCount = 1000;
|
||
let calculateZ = function () {
|
||
let minMaxOx = t._getMinMaxOxPoints(newPoints, -t.cameraDiffZ);
|
||
t.cameraDiffX = -minMaxOx.diffX;
|
||
let x111 = t.convertAndTurnPoint(minMaxOx.tempX1, minMaxOx.tempY1, minMaxOx.tempZ1);
|
||
let x222 = t.convertAndTurnPoint(minMaxOx.tempX2, minMaxOx.tempY2, minMaxOx.tempZ2);
|
||
|
||
let diffX = Math.abs(x222.x - x111.x);
|
||
|
||
let minMaxOy = t._getMinMaxOyPoints(newPoints, t.cameraDiffZ);
|
||
t.cameraDiffY = -minMaxOy.diffY;
|
||
let y111 = t.convertAndTurnPoint(minMaxOy.tempX1, minMaxOy.tempY1, minMaxOy.tempZ1);
|
||
let y222 = t.convertAndTurnPoint(minMaxOy.tempX2, minMaxOy.tempY2, minMaxOy.tempZ2);
|
||
|
||
let diffY = Math.abs(y222.y - y111.y);
|
||
|
||
if (diffX <= widthChart && diffY <= heightChart && ((widthChart - diffX) < DELTA || (heightChart - diffY) < DELTA)) {
|
||
return;
|
||
}
|
||
|
||
let count = 0;
|
||
let fStart = t.cameraDiffZ ? t.cameraDiffZ : 1;
|
||
let fLeftDiffZ, fRightDiffZ;
|
||
if (diffX < widthChart && diffY < heightChart) {
|
||
fLeftDiffZ = 0;
|
||
fRightDiffZ = t.cameraDiffZ;
|
||
} else {
|
||
fLeftDiffZ = t.cameraDiffZ;
|
||
while (diffX >= widthChart || diffY >= heightChart) {
|
||
count++;
|
||
t.cameraDiffZ += fStart / 2;
|
||
minMaxOx = t._getMinMaxOxPoints(newPoints, -t.cameraDiffZ);
|
||
t.cameraDiffX = -minMaxOx.diffX;
|
||
x111 = t.convertAndTurnPoint(minMaxOx.tempX1, minMaxOx.tempY1, minMaxOx.tempZ1);
|
||
x222 = t.convertAndTurnPoint(minMaxOx.tempX2, minMaxOx.tempY2, minMaxOx.tempZ2);
|
||
diffX = Math.abs(x222.x - x111.x);
|
||
minMaxOy = t._getMinMaxOyPoints(newPoints, t.cameraDiffZ);
|
||
t.cameraDiffY = -minMaxOy.diffY;
|
||
y111 = t.convertAndTurnPoint(minMaxOy.tempX1, minMaxOy.tempY1, minMaxOy.tempZ1);
|
||
y222 = t.convertAndTurnPoint(minMaxOy.tempX2, minMaxOy.tempY2, minMaxOy.tempZ2);
|
||
diffY = Math.abs(y222.y - y111.y);
|
||
|
||
if (count > maxCount) {
|
||
return;
|
||
}
|
||
}
|
||
if (diffX <= widthChart && diffY <= heightChart && ((widthChart - diffX) < DELTA || (heightChart - diffY) < DELTA)) {
|
||
return;
|
||
}
|
||
fRightDiffZ = t.cameraDiffZ;
|
||
}
|
||
|
||
|
||
while ((diffX > widthChart || diffY > heightChart) || (fRightDiffZ - fLeftDiffZ) > DELTA) {
|
||
t.cameraDiffZ = fLeftDiffZ + ((fRightDiffZ - fLeftDiffZ) / 2);
|
||
|
||
count++;
|
||
minMaxOx = t._getMinMaxOxPoints(newPoints, -t.cameraDiffZ);
|
||
t.cameraDiffX = -minMaxOx.diffX;
|
||
let x111 = t.convertAndTurnPoint(minMaxOx.tempX1, minMaxOx.tempY1, minMaxOx.tempZ1);
|
||
let x222 = t.convertAndTurnPoint(minMaxOx.tempX2, minMaxOx.tempY2, minMaxOx.tempZ2);
|
||
|
||
|
||
let diffX = Math.abs(x222.x - x111.x);
|
||
|
||
let minMaxOy = t._getMinMaxOyPoints(newPoints, t.cameraDiffZ);
|
||
t.cameraDiffY = -minMaxOy.diffY;
|
||
let y111 = t.convertAndTurnPoint(minMaxOy.tempX1, minMaxOy.tempY1, minMaxOy.tempZ1);
|
||
let y222 = t.convertAndTurnPoint(minMaxOy.tempX2, minMaxOy.tempY2, minMaxOy.tempZ2);
|
||
|
||
let diffY = Math.abs(y222.y - y111.y);
|
||
if (diffX < widthChart && diffY < heightChart) {
|
||
if (((widthChart - diffX) < DELTA) || ((heightChart - diffY) < DELTA)) {
|
||
break;
|
||
}
|
||
fRightDiffZ = t.cameraDiffZ;
|
||
} else {
|
||
fLeftDiffZ = t.cameraDiffZ;
|
||
}
|
||
|
||
if (count > maxCount) {
|
||
return;
|
||
}
|
||
}
|
||
};
|
||
|
||
calculateZ();
|
||
|
||
};
|
||
|
||
Processor3D.prototype._getMinMaxOxPoints = function (points, minZ) {
|
||
let fov = 1 / this.rPerspective;
|
||
|
||
let t = this;
|
||
let aspectRatioX = this.aspectRatioX;
|
||
let aspectRatioY = this.aspectRatioY;
|
||
|
||
|
||
let diffAndRotatePoint = function (point) {
|
||
let point3D = new Point3D(point.x, point.y, point.z, t);
|
||
|
||
point3D.scale(aspectRatioX, aspectRatioY, 1);
|
||
point3D.offset((-t.widthCanvas / 2) / aspectRatioX, (-t.heightCanvas / 2) / aspectRatioY /** aspectRatio*/, 0);
|
||
|
||
//rotate
|
||
let matrixRotateAllAxis = t._getMatrixRotateAllAxis();
|
||
point3D.multiplyPointOnMatrix1(matrixRotateAllAxis);
|
||
|
||
return point3D;
|
||
};
|
||
|
||
let calculateDiffX = function (x1, x2, z1, z2, minZ, y1, y2) {
|
||
let diffAndScalePoints1 = t.diffAndScale(x1, y1, z1);
|
||
x1 = diffAndScalePoints1.x;
|
||
y1 = diffAndScalePoints1.y;
|
||
z1 = diffAndScalePoints1.z;
|
||
|
||
let rotatePoints1 = t.rotate(x1, y1, z1);
|
||
|
||
let a1 = rotatePoints1.x;
|
||
//let x1S = a1 - diffX;
|
||
let z1S = rotatePoints1.z - minZ;
|
||
//let x1SS = (fov * x1S / (z1S + fov)) + w / 2;
|
||
|
||
|
||
let diffAndScalePoints2 = t.diffAndScale(x2, y2, z2);
|
||
x2 = diffAndScalePoints2.x;
|
||
y2 = diffAndScalePoints2.y;
|
||
z2 = diffAndScalePoints2.z;
|
||
|
||
let rotatePoints2 = t.rotate(x2, y2, z2);
|
||
|
||
let a2 = rotatePoints2.x;
|
||
//let x2S = a2 - diffX;
|
||
let z2S = rotatePoints2.z - minZ;
|
||
//let x2SS = (fov * x2S / (z2S + fov)) + w / 2;
|
||
|
||
return (-a1 * z2S - a1 * fov - a2 * z1S - a2 * fov) / (-z2S - fov - z1S - fov);
|
||
};
|
||
|
||
|
||
let w = t.widthCanvas;
|
||
|
||
let tempArray = this._getArrayAllVergeCube(points);
|
||
|
||
let diffX;
|
||
let x11, x22, y11, y22, z11, z22;
|
||
let tempX1, tempY1, tempZ1, tempX2, tempY2, tempZ2, start, end;
|
||
for (let i = 0; i < tempArray.length - 1; i++) {
|
||
start = i;
|
||
end = i + 1;
|
||
x11 = tempArray[start].x - (t.widthCanvas / 2);
|
||
x22 = tempArray[end].x - (t.widthCanvas / 2);
|
||
|
||
y11 = tempArray[start].y - (t.heightCanvas / 2);
|
||
y22 = tempArray[end].y - (t.heightCanvas / 2);
|
||
|
||
z11 = tempArray[start].z;
|
||
z22 = tempArray[end].z;
|
||
|
||
tempX1 = tempArray[start].x;
|
||
tempY1 = tempArray[start].y;
|
||
tempZ1 = tempArray[start].z;
|
||
|
||
tempX2 = tempArray[end].x;
|
||
tempY2 = tempArray[end].y;
|
||
tempZ2 = tempArray[end].z;
|
||
|
||
if (x11 > x22) {
|
||
start = i + 1;
|
||
end = i;
|
||
x11 = tempArray[start].x - (t.widthCanvas / 2);
|
||
x22 = tempArray[end].x - (t.widthCanvas / 2);
|
||
|
||
y11 = tempArray[start].y - (t.heightCanvas / 2);
|
||
y22 = tempArray[end].y - (t.heightCanvas / 2);
|
||
|
||
z11 = tempArray[start].z;
|
||
z22 = tempArray[end].z;
|
||
|
||
tempX1 = tempArray[start].x;
|
||
tempY1 = tempArray[start].y;
|
||
tempZ1 = tempArray[start].z;
|
||
|
||
tempX2 = tempArray[end].x;
|
||
tempY2 = tempArray[end].y;
|
||
tempZ2 = tempArray[end].z;
|
||
}
|
||
|
||
|
||
diffX = calculateDiffX(tempX1, tempX2, tempZ1, tempZ2, minZ, tempY1, tempY2);
|
||
|
||
let projectiveMatrix = t._getPerspectiveProjectionMatrix(1 / (t.rPerspective));
|
||
|
||
let rotatePoint1 = diffAndRotatePoint(tempArray[start]);
|
||
rotatePoint1.offset(-diffX, 0, -minZ);
|
||
rotatePoint1 = rotatePoint1.project(projectiveMatrix);
|
||
let x1 = Math.floor(rotatePoint1.x + t.widthCanvas / 2);
|
||
|
||
|
||
let rotatePoint2 = diffAndRotatePoint(tempArray[end]);
|
||
rotatePoint2.offset(-diffX, 0, -minZ);
|
||
rotatePoint2 = rotatePoint2.project(projectiveMatrix);
|
||
let x2 = Math.floor(rotatePoint2.x + t.widthCanvas / 2);
|
||
|
||
let leftMargin = x1;
|
||
let rightMargin = Math.floor(w - x2);
|
||
if (!((leftMargin >= rightMargin - 1) && (leftMargin <= rightMargin + 1))) {
|
||
continue;
|
||
}
|
||
|
||
let isTrue = true;
|
||
for (let l = 0; l < tempArray.length - 1; l++) {
|
||
let rotatePoint = diffAndRotatePoint(tempArray[l]);
|
||
rotatePoint.offset(-diffX, 0, -minZ);
|
||
rotatePoint = rotatePoint.project(projectiveMatrix);
|
||
let tempX11 = Math.floor(rotatePoint.x + t.widthCanvas / 2);
|
||
|
||
|
||
if (x1 < x2) {
|
||
if (tempX11 < x1 || tempX11 > x2) {
|
||
isTrue = false;
|
||
break;
|
||
}
|
||
} else {
|
||
if (tempX11 > x1 || tempX11 < x2) {
|
||
isTrue = false;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (isTrue) {
|
||
break;
|
||
}
|
||
}
|
||
|
||
return {
|
||
diffX: diffX, tempX1: tempX1, tempY1: tempY1, tempZ1: tempZ1, tempX2: tempX2, tempY2: tempY2, tempZ2: tempZ2, x11: x11, z11: z11, x22: x22, z22: z22, y11: y11, y22: y22
|
||
};
|
||
};
|
||
|
||
Processor3D.prototype._getMinMaxOyPoints = function (points, minZ) {
|
||
let fov = 1 / this.rPerspective;
|
||
let t = this;
|
||
let h = t.heightCanvas;
|
||
|
||
let calculateDiffY = function (x1, x2, y1, y2, z1, z2, minZ) {
|
||
//let cos1 = Math.cos(-t.angleOy);
|
||
//let sin1 = Math.sin(-t.angleOy);
|
||
let diffY = 0;
|
||
|
||
let diffAndScalePoints = t.diffAndScale(x1, y1, z1);
|
||
x1 = diffAndScalePoints.x;
|
||
y1 = diffAndScalePoints.y;
|
||
z1 = diffAndScalePoints.z;
|
||
|
||
|
||
let rotatePoints = t.rotate(x1, y1, z1);
|
||
|
||
let a1 = rotatePoints.y;
|
||
//let y1S = (a1 - diffY);
|
||
let z1S = rotatePoints.z + minZ;
|
||
|
||
//let x1SS = (fov * y1S / (z1S + fov)) + h / 2;
|
||
|
||
|
||
diffAndScalePoints = t.diffAndScale(x2, y2, z2);
|
||
x2 = diffAndScalePoints.x;
|
||
y2 = diffAndScalePoints.y;
|
||
z2 = diffAndScalePoints.z;
|
||
|
||
rotatePoints = t.rotate(x2, y2, z2);
|
||
|
||
let a2 = rotatePoints.y;
|
||
//let y2S = (a2 - diffY);
|
||
let z2S = rotatePoints.z + minZ;
|
||
|
||
//let x2SS = (fov * y2S / (z2S + fov)) + h / 2;
|
||
|
||
//let topMargin = (fov * y1S / (z1S + fov)) + h / 2;
|
||
//let bottomMargin = h - ((fov * y2S / (z2S + fov)) + h / 2);
|
||
|
||
|
||
//((a1 - diffY) / (z1S + fov)) = - (((a2 - diffY) / (z2S + fov)))
|
||
|
||
/*(a1 - diffY) * (z2S + fov) = -(z1S + fov) * (a2 - diffY)
|
||
|
||
a1 * z2S + a1 * fov - diffY * z2S - diffY * fov = -z1S * a2 + z1S * diffY - fov * a2 + fov * diffY
|
||
|
||
a1 * z2S + a1 * fov + fov * a2 + z1S * a2= diffY * z2S + diffY * fov + z1S * diffY + fov * diffY*/
|
||
|
||
diffY = (a1 * z2S + a1 * fov + fov * a2 + z1S * a2) / (z2S + fov + z1S + fov);
|
||
|
||
//let diffY = (-a1 * z2S - a1 * fov - a2 * z1S -a2 * fov) / ( -z2S - fov - z1S - fov);
|
||
|
||
|
||
return diffY;
|
||
|
||
};
|
||
|
||
let tempArray = this._getArrayAllVergeCube(points);
|
||
|
||
let diffY;
|
||
let tempX1, tempY1, tempZ1, tempX2, tempY2, tempZ2;
|
||
for (let i = 0; i < tempArray.length - 1; i++) {
|
||
let start = i;
|
||
let end = i + 1;
|
||
|
||
tempX1 = tempArray[start].x;
|
||
tempY1 = tempArray[start].y;
|
||
tempZ1 = tempArray[start].z;
|
||
|
||
tempX2 = tempArray[end].x;
|
||
tempY2 = tempArray[end].y;
|
||
tempZ2 = tempArray[end].z;
|
||
|
||
if (tempY1 > tempY2) {
|
||
start = i + 1;
|
||
end = i;
|
||
|
||
tempX1 = tempArray[start].x;
|
||
tempY1 = tempArray[start].y;
|
||
tempZ1 = tempArray[start].z;
|
||
|
||
tempX2 = tempArray[end].x;
|
||
tempY2 = tempArray[end].y;
|
||
tempZ2 = tempArray[end].z;
|
||
}
|
||
|
||
|
||
diffY = calculateDiffY(tempX1, tempX2, tempY1, tempY2, tempZ1, tempZ2, minZ);
|
||
|
||
let rotatePoint1 = this.calculatePointManual(tempX1, tempY1, tempZ1, this.cameraDiffX, -diffY, minZ);
|
||
let y1 = rotatePoint1.y;
|
||
|
||
|
||
let rotatePoint2 = this.calculatePointManual(tempX2, tempY2, tempZ2, this.cameraDiffX, -diffY, minZ);
|
||
let y2 = rotatePoint2.y;
|
||
|
||
let topMargin = y1;
|
||
let bottomMargin = Math.floor(h - y2);
|
||
if (!((topMargin >= bottomMargin - 1) && (topMargin <= bottomMargin + 1))) {
|
||
continue;
|
||
}
|
||
|
||
let isTrue = true;
|
||
for (let l = 0; l < tempArray.length - 1; l++) {
|
||
let rotatePoint = this.calculatePointManual(tempArray[l].x, tempArray[l].y, tempArray[l].z, this.cameraDiffX, -diffY, minZ);
|
||
let tempY11 = rotatePoint.y;
|
||
|
||
if (y1 < y2) {
|
||
if (tempY11 < y1 || tempY11 > y2) {
|
||
isTrue = false;
|
||
break;
|
||
}
|
||
} else {
|
||
if (tempY11 > y1 || tempY11 < y2) {
|
||
isTrue = false;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (isTrue) {
|
||
break;
|
||
}
|
||
}
|
||
|
||
return {
|
||
diffY: diffY, tempX1: tempX1, tempY1: tempY1, tempZ1: tempZ1, tempX2: tempX2, tempY2: tempY2, tempZ2: tempZ2
|
||
};
|
||
};
|
||
|
||
Processor3D.prototype._getArrayAllVergeCube = function (points) {
|
||
let res = [];
|
||
|
||
res[0] = points[0];
|
||
res[1] = points[1];
|
||
res[2] = points[2];
|
||
res[3] = points[3];
|
||
res[4] = points[0];
|
||
res[5] = points[4];
|
||
res[6] = points[7];
|
||
res[7] = points[6];
|
||
res[8] = points[5];
|
||
res[9] = points[2];
|
||
res[10] = points[6];
|
||
res[11] = points[1];
|
||
res[12] = points[7];
|
||
res[13] = points[0];
|
||
res[14] = points[5];
|
||
res[15] = points[1];
|
||
res[16] = points[4];
|
||
res[17] = points[3];
|
||
res[18] = points[6];
|
||
res[19] = points[0];
|
||
res[20] = points[2];
|
||
res[21] = points[7];
|
||
res[22] = points[3];
|
||
res[23] = points[5];
|
||
res[24] = points[7];
|
||
res[25] = points[4];
|
||
res[26] = points[2];
|
||
res[27] = points[3];
|
||
res[28] = points[1];
|
||
res[29] = points[4];
|
||
res[30] = points[5];
|
||
res[31] = points[6];
|
||
res[32] = points[4];
|
||
|
||
|
||
/*for(let i = 0; i < points.length; i++)
|
||
{
|
||
for(let j = 0; j < points.length; j++)
|
||
{
|
||
res.push(points[i]);
|
||
res.push(points[j]);
|
||
|
||
}
|
||
}*/
|
||
|
||
return res;
|
||
};
|
||
|
||
Processor3D.prototype._getMinMaxOyPoints2 = function (points, minZ) {
|
||
let t = this;
|
||
|
||
let h = t.heightCanvas;
|
||
|
||
let tempArray = [];
|
||
tempArray[0] = points[0];//leftNear
|
||
tempArray[1] = points[1];//leftFar
|
||
tempArray[2] = points[2];//rightFar
|
||
tempArray[3] = points[3];//rightNear
|
||
tempArray[4] = points[4];//leftNear
|
||
tempArray[5] = points[5];//leftFar
|
||
tempArray[6] = points[6];//leftFar
|
||
tempArray[7] = points[7];//leftFar
|
||
tempArray[8] = points[4];//leftFar
|
||
tempArray[9] = points[1];//leftFar
|
||
tempArray[10] = points[3];//leftFar
|
||
tempArray[11] = points[0];//leftFar
|
||
tempArray[12] = points[7];//leftFar
|
||
tempArray[13] = points[2];//leftFar
|
||
tempArray[14] = points[0];//leftFar
|
||
tempArray[15] = points[6];//leftFar
|
||
tempArray[16] = points[5];//leftFar
|
||
tempArray[17] = points[0];//leftFar
|
||
tempArray[18] = points[4];//leftFar
|
||
|
||
|
||
let tempX1, tempY1, tempZ1, tempX2, tempY2, tempZ2;
|
||
for (let i = 0; i < tempArray.length - 1; i++) {
|
||
let start = i;
|
||
let end = i + 1;
|
||
|
||
tempX1 = tempArray[start].x;
|
||
tempY1 = tempArray[start].y;
|
||
tempZ1 = tempArray[start].z;
|
||
|
||
tempX2 = tempArray[end].x;
|
||
tempY2 = tempArray[end].y;
|
||
tempZ2 = tempArray[end].z;
|
||
|
||
if (tempY1 > tempY2) {
|
||
start = i + 1;
|
||
end = i;
|
||
|
||
tempX1 = tempArray[start].x;
|
||
tempY1 = tempArray[start].y;
|
||
tempZ1 = tempArray[start].z;
|
||
|
||
tempX2 = tempArray[end].x;
|
||
tempY2 = tempArray[end].y;
|
||
tempZ2 = tempArray[end].z;
|
||
}
|
||
|
||
|
||
//let diffY = calculateDiffY(tempX1, tempX2, tempY1, tempY2, tempZ1, tempZ2, minZ);
|
||
|
||
|
||
let correctOffset = this._correctZPositionOY(tempX1, tempX2, tempZ1, tempZ2, minZ, tempY1, tempY2);
|
||
let diffZ = correctOffset.minZ;
|
||
let diffY = correctOffset.diffY;
|
||
|
||
|
||
let rotatePoint1 = this.calculatePointManual(tempX1, tempY1, tempZ1, this.cameraDiffX, diffY, diffZ);
|
||
let y1 = rotatePoint1.y;
|
||
|
||
|
||
let rotatePoint2 = this.calculatePointManual(tempX2, tempY2, tempZ2, this.cameraDiffX, diffY, diffZ);
|
||
let y2 = rotatePoint2.y;
|
||
|
||
let topMargin = y1;
|
||
let bottomMargin = Math.floor(h - y2);
|
||
if (!((topMargin >= bottomMargin - 1) && (topMargin <= bottomMargin + 1))) {
|
||
continue;
|
||
}
|
||
|
||
let isTrue = true;
|
||
for (let l = 0; l < tempArray.length - 1; l++) {
|
||
let rotatePoint = this.calculatePointManual(tempArray[l].x, tempArray[l].y, tempArray[l].z, this.cameraDiffX, diffY, diffZ);
|
||
let tempY11 = rotatePoint.y;
|
||
|
||
if (y1 < y2) {
|
||
if (tempY11 < y1 || tempY11 > y2) {
|
||
isTrue = false;
|
||
break;
|
||
}
|
||
} else {
|
||
if (tempY11 > y1 || tempY11 < y2) {
|
||
isTrue = false;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (isTrue) {
|
||
break;
|
||
}
|
||
}
|
||
|
||
return {
|
||
tempX1: tempX1, tempY1: tempY1, tempZ1: tempZ1, tempX2: tempX2, tempY2: tempY2, tempZ2: tempZ2
|
||
};
|
||
};
|
||
|
||
Processor3D.prototype._correctZPosition4 = function (x1, x2, z1, z2, minZ, y1, y2) {
|
||
let t = this;
|
||
|
||
let getDiffXZ3 = function (x1, x2, z1, z2, y1, y2) {
|
||
let w = t.widthCanvas;
|
||
|
||
let fov = 1 / t.rPerspective;
|
||
|
||
let diffAndScalePoints = t.diffAndScale(x1, y1, z1);
|
||
let x11 = diffAndScalePoints.x;
|
||
let y11 = diffAndScalePoints.y;
|
||
let z11 = diffAndScalePoints.z;
|
||
|
||
|
||
let rotatePoints = t.rotate(x11, y11, z11);
|
||
let x111 = rotatePoints.x;
|
||
let z111 = rotatePoints.z;
|
||
|
||
|
||
/*let x1111 = x111 + diffX;
|
||
let y1111 = y111 + diffY;
|
||
let z1111 = z111 + diffZ;
|
||
let x11111 = (fov * x1111) / (z1111 + fov) + w / 2;
|
||
let y11111 = (fov * y1111) / (z1111 + fov) + h / 2;*/
|
||
|
||
|
||
//(fov * x1111) / (z1111 + fov) + w / 2 = t.left
|
||
//(fov * (x111 + diffX)) / ((z111 + diffZ) + fov) + w / 2 = t.left
|
||
let wL = t.left - w / 2;
|
||
//fov * (x111 + diffX) = wL * ((z111 + diffZ) + fov)
|
||
//fov * x111 + fov * diffX = wL * z111 + wL * diffZ + wL * fov
|
||
|
||
|
||
diffAndScalePoints = t.diffAndScale(x2, y2, z2);
|
||
let x22 = diffAndScalePoints.x;
|
||
let y22 = diffAndScalePoints.y;
|
||
let z22 = diffAndScalePoints.z;
|
||
|
||
|
||
rotatePoints = t.rotate(x22, y22, z22);
|
||
let x222 = rotatePoints.x;
|
||
let z222 = rotatePoints.z;
|
||
|
||
|
||
/*let x1111 = x111 + diffX;
|
||
let y1111 = y111 + diffY;
|
||
let z1111 = z111 + diffZ;
|
||
let x11111 = (fov * x1111) / (z1111 + fov) + w / 2;
|
||
let y11111 = (fov * y1111) / (z1111 + fov) + h / 2;*/
|
||
|
||
|
||
let wR = w / 2 - t.left;
|
||
//fov * (x222 + diffX) = wR * ((z222 + diffZ) + fov)
|
||
//fov * x222 + fov * diffX = wR * z222 + wR * diffZ + wR * fov
|
||
|
||
|
||
//итого
|
||
//fov * x111 + fov * diffX = wL * z111 + wL * diffZ + wL * fov
|
||
//fov * x222 + fov * diffX = wR * z222 + wR * diffZ + wR * fov
|
||
|
||
|
||
/*diffX = (wL * z111 + wL * diffZ + wL * fov - fov * x111) / fov;
|
||
|
||
fov * x222 + wL * z111 + wL * diffZ + wL * fov - fov * x111 = wR * z222 + wR * diffZ + wR * fov
|
||
|
||
fov * x222 + wL * z111 + wL * fov - fov * x111 - wR * z222 - wR * fov = wR * diffZ - wL * diffZ*/
|
||
|
||
|
||
let diffZ = (fov * x222 + wL * z111 + wL * fov - fov * x111 - wR * z222 - wR * fov) / (wR - wL);
|
||
let diffX = (wL * z111 + wL * diffZ + wL * fov - fov * x111) / fov;
|
||
|
||
|
||
return {minZ: diffZ, diffX: diffX};
|
||
};
|
||
|
||
let diffXZ3 = getDiffXZ3(x1, x2, z1, z2, y1, y2);
|
||
|
||
return {minZ: diffXZ3.minZ, diffX: diffXZ3.diffX};
|
||
};
|
||
|
||
Processor3D.prototype._correctZPositionOY = function (x1, x2, z1, z2, minZ, y1, y2) {
|
||
let t = this;
|
||
|
||
let getDiffXZ3 = function (x1, x2, z1, z2, y1, y2) {
|
||
let h = t.heightCanvas;
|
||
|
||
let fov = 1 / t.rPerspective;
|
||
|
||
let diffAndScalePoints = t.diffAndScale(x1, y1, z1);
|
||
let x11 = diffAndScalePoints.x;
|
||
let y11 = diffAndScalePoints.y;
|
||
let z11 = diffAndScalePoints.z;
|
||
|
||
|
||
let rotatePoints = t.rotate(x11, y11, z11);
|
||
let y111 = rotatePoints.y;
|
||
let z111 = rotatePoints.z;
|
||
|
||
|
||
/*let x1111 = x111 + diffX;
|
||
let y1111 = y111 + diffY;
|
||
let z1111 = z111 + diffZ;
|
||
let x11111 = (fov * x1111) / (z1111 + fov) + w / 2;
|
||
let y11111 = (fov * y1111) / (z1111 + fov) + h / 2;*/
|
||
|
||
|
||
//(fov * x1111) / (z1111 + fov) + w / 2 = t.left
|
||
//(fov * (x111 + diffX)) / ((z111 + diffZ) + fov) + w / 2 = t.left
|
||
//let wL = t.left - w / 2;
|
||
//fov * (x111 + diffX) = wL * ((z111 + diffZ) + fov)
|
||
//fov * x111 + fov * diffX = wL * z111 + wL * diffZ + wL * fov
|
||
|
||
|
||
diffAndScalePoints = t.diffAndScale(x2, y2, z2);
|
||
let x22 = diffAndScalePoints.x;
|
||
let y22 = diffAndScalePoints.y;
|
||
let z22 = diffAndScalePoints.z;
|
||
|
||
|
||
rotatePoints = t.rotate(x22, y22, z22);
|
||
let y222 = rotatePoints.y;
|
||
let z222 = rotatePoints.z;
|
||
|
||
|
||
/*let x1111 = x111 + diffX;
|
||
let y1111 = y111 + diffY;
|
||
let z1111 = z111 + diffZ;
|
||
let x11111 = (fov * x1111) / (z1111 + fov) + w / 2;
|
||
let y11111 = (fov * y1111) / (z1111 + fov) + h / 2;*/
|
||
|
||
|
||
//(fov * (y111 + diffY)) / ((z111 + diffZ) + fov) + h / 2 = t.top
|
||
//(fov * (y222 + diffY)) / ((z222 + diffZ) + fov) + h / 2 = h - t.bottom
|
||
let wL = t.top - h / 2;
|
||
let wR = h / 2 - t.bottom;
|
||
|
||
/*(fov * (y111 + diffY)) / ((z111 + diffZ) + fov) = wL
|
||
(fov * (y222 + diffY)) / ((z222 + diffZ) + fov) = wR
|
||
|
||
|
||
fov * (y111 + diffY) = wL * ((z111 + diffZ) + fov)
|
||
|
||
fov * y111 + fov * diffY = wL * z111 + wL * diffZ + wL * fov
|
||
fov * y222 + fov * diffY = wR * z222 + wR * diffZ + wR * fov
|
||
|
||
diffY = (wR * z222 + wR * diffZ + wR * fov - fov * y222) / fov
|
||
|
||
fov * y111 + wR * z222 + wR * diffZ + wR * fov - fov * y222 = wL * z111 + wL * diffZ + wL * fov
|
||
|
||
fov * y111 + wR * z222 + wR * fov - fov * y222 - wL * z111 - wL * fov = wL * diffZ - wR * diffZ*/
|
||
|
||
let diffZ = (fov * y111 + wR * z222 + wR * fov - fov * y222 - wL * z111 - wL * fov) / (wL - wR);
|
||
let diffY = (wR * z222 + wR * diffZ + wR * fov - fov * y222) / fov;
|
||
|
||
|
||
//let diffZ = (fov * x222 + wL * z111 + wL * fov - fov * x111 - wR * z222 - wR * fov) / (wR - wL);
|
||
//let diffX = (wL * z111 + wL * diffZ + wL * fov - fov * x111) / fov;
|
||
|
||
|
||
return {minZ: diffZ, diffY: diffY};
|
||
};
|
||
|
||
let diffXZ3 = getDiffXZ3(x1, x2, z1, z2, y1, y2);
|
||
|
||
return {minZ: diffXZ3.minZ, diffY: diffXZ3.diffY};
|
||
};
|
||
|
||
Processor3D.prototype._calculateCameraDiffX = function (minMaxOx) {
|
||
//test ровно по центру, но циклом
|
||
let maxLeftPoint = minMaxOx.left;
|
||
let maxRightPoint = minMaxOx.right;
|
||
|
||
//так ближе к тому, как смещает excel
|
||
let widthCanvas = this.widthCanvas;
|
||
let originalWidthChart = widthCanvas - this.left - this.right;
|
||
|
||
let diffLeft = maxLeftPoint - this.left;
|
||
let diffRight = (this.left + originalWidthChart) - maxRightPoint;
|
||
|
||
this.cameraDiffX = (((diffRight - diffLeft) / 2) * (1 / (this.rPerspective) + this.cameraDiffZ)) / (1 / (this.rPerspective));
|
||
};
|
||
|
||
Processor3D.prototype._calculateCameraDiffY = function (maxTopPoint, maxBottomPoint) {
|
||
let top = this.top;
|
||
let bottom = this.bottom;
|
||
let heightCanvas = this.heightCanvas;
|
||
let heightChart = heightCanvas - top - bottom;
|
||
|
||
let diffTop = maxTopPoint - top;
|
||
let diffBottom = (heightChart + top) - maxBottomPoint;
|
||
|
||
//this.cameraDiffY = this.top - minMaxOy.top; - для rAngAx
|
||
this.cameraDiffY = (diffBottom - diffTop) / 2;
|
||
};
|
||
|
||
Processor3D.prototype._getMinMaxOx = function (points, faces) {
|
||
let mostLeftPointX;
|
||
let mostRightPointX;
|
||
let xRight;
|
||
let xLeft;
|
||
|
||
for (let i = 0; i < faces.length - 1; i++) {
|
||
for (let k = 0; k <= 3; k++) {
|
||
|
||
let point1 = this.convertAndTurnPoint(points[faces[i][k]].x, points[faces[i][k]].y, points[faces[i][k]].z);
|
||
//let point2 = this.convertAndTurnPoint(points[faces[i][k + 1]].x, points[faces[i][k + 1]].y, points[faces[i][k + 1]].z, true);
|
||
let x1 = point1.x;
|
||
//let x2 = point2.x;
|
||
|
||
if (!xLeft) {
|
||
xLeft = x1;
|
||
mostLeftPointX = new Point3D(points[faces[i][k]].x, points[faces[i][k]].y, points[faces[i][k]].z, this.cChartDrawer);
|
||
|
||
xRight = x1;
|
||
mostRightPointX = new Point3D(points[faces[i][k]].x, points[faces[i][k]].y, points[faces[i][k]].z, this.cChartDrawer);
|
||
} else {
|
||
if (x1 < xLeft) {
|
||
xLeft = x1;
|
||
mostLeftPointX = new Point3D(points[faces[i][k]].x, points[faces[i][k]].y, points[faces[i][k]].z, this.cChartDrawer);
|
||
}
|
||
|
||
if (x1 > xRight) {
|
||
xRight = x1;
|
||
mostRightPointX = new Point3D(points[faces[i][k]].x, points[faces[i][k]].y, points[faces[i][k]].z, this.cChartDrawer);
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
return {left: xLeft, right: xRight, mostLeftPointX: mostLeftPointX, mostRightPointX: mostRightPointX};
|
||
};
|
||
|
||
Processor3D.prototype._getMinMaxOy = function (points, faces) {
|
||
let mostTopPointY;
|
||
let mostBottomPointY;
|
||
let xTop = this.top + this.heightCanvas;
|
||
let xBottom = 0;
|
||
for (let i = 0; i < faces.length - 1; i++) {
|
||
for (let k = 0; k < 3; k++) {
|
||
|
||
let point1 = this.convertAndTurnPoint(points[faces[i][k]].x, points[faces[i][k]].y, points[faces[i][k]].z);
|
||
let point2 = this.convertAndTurnPoint(points[faces[i][k + 1]].x, points[faces[i][k + 1]].y, points[faces[i][k + 1]].z);
|
||
let y1 = point1.y;
|
||
let y2 = point2.y;
|
||
|
||
|
||
if (y1 <= xTop) {
|
||
xTop = y1;
|
||
mostTopPointY = new Point3D(points[faces[i][k]].x, points[faces[i][k]].y, points[faces[i][k]].z, this.cChartDrawer);
|
||
}
|
||
|
||
if (y2 <= xTop) {
|
||
xTop = y2;
|
||
mostTopPointY = new Point3D(points[faces[i][k + 1]].x, points[faces[i][k + 1]].y, points[faces[i][k + 1]].z, this.cChartDrawer);
|
||
}
|
||
|
||
if (y1 >= xBottom) {
|
||
xBottom = y1;
|
||
mostBottomPointY = new Point3D(points[faces[i][k]].x, points[faces[i][k]].y, points[faces[i][k]].z, this.cChartDrawer);
|
||
}
|
||
|
||
if (y2 >= xBottom) {
|
||
xBottom = y2;
|
||
mostBottomPointY = new Point3D(points[faces[i][k + 1]].x, points[faces[i][k + 1]].y, points[faces[i][k + 1]].z, this.cChartDrawer);
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
return {top: xTop, bottom: xBottom, mostTopPointY: mostTopPointY, mostBottomPointY: mostBottomPointY};
|
||
};
|
||
|
||
Processor3D.prototype._calcAspectRatio = function () {
|
||
//return width / height
|
||
let widthOriginalChart = this.widthCanvas - (this.left + this.right);
|
||
let heightOriginalChart = this.heightCanvas - (this.top + this.bottom);
|
||
//auto scale if hPercent == null
|
||
let hPercent = this.hPercent;
|
||
let depthPercent = this._getDepthPercent();
|
||
|
||
let aspectRatioX = 1;
|
||
let aspectRatioY = 1;
|
||
|
||
let countSeries = this.chartsDrawer.calculateFirstChartCountSeries();
|
||
let seriesCount = countSeries.series;
|
||
let ptCount = countSeries.points;
|
||
|
||
let subType = this.chartsDrawer.calcProp.subType;
|
||
if ((subType === "standard" || this.chartsDrawer.calcProp.type === AscFormat.c_oChartTypes.Line ||
|
||
(this.chartsDrawer.calcProp.type === AscFormat.c_oChartTypes.Area && subType === "normal") || this.chartsDrawer.calcProp.type === AscFormat.c_oChartTypes.Surface) &&
|
||
!this.view3D.getRAngAx()) {
|
||
this._calcSpecialStandardScaleX();
|
||
|
||
aspectRatioX = (widthOriginalChart / (heightOriginalChart / hPercent)) * this.specialStandardScaleX;
|
||
} else if (subType === "standard" || this.chartsDrawer.calcProp.type === AscFormat.c_oChartTypes.Line || this.chartsDrawer.calcProp.type ===
|
||
AscFormat.c_oChartTypes.Surface) {
|
||
|
||
let depth = this.view3D.getRAngAx() ? this._calculateDepth() : this._calculateDepthPerspective();
|
||
let width = (depth / depthPercent) * (ptCount / seriesCount);
|
||
|
||
aspectRatioX = (widthOriginalChart) / width;
|
||
} else if (hPercent !== null)//auto scale height
|
||
{
|
||
aspectRatioX = widthOriginalChart / (heightOriginalChart / hPercent);
|
||
}
|
||
|
||
if (aspectRatioX < 1 && this.view3D.getRAngAx()) {
|
||
aspectRatioY = 1 / aspectRatioX;
|
||
aspectRatioX = 1;
|
||
}
|
||
|
||
this.aspectRatioX = aspectRatioX;
|
||
this.aspectRatioY = aspectRatioY;
|
||
};
|
||
|
||
Processor3D.prototype._getDepthPercent = function () {
|
||
if (AscFormat.c_oChartTypes.Pie === this.chartsDrawer.calcProp.type) {
|
||
return globalBasePercent / 100;
|
||
}
|
||
return this.view3D && this.view3D.depthPercent ? this.view3D.depthPercent / 100 : globalBasePercent / 100;
|
||
};
|
||
|
||
|
||
function Point3D(x, y, z, chartsDrawer) {
|
||
this.x = x;
|
||
this.y = y;
|
||
this.z = z;
|
||
this.t = 1;
|
||
|
||
if (chartsDrawer) {
|
||
this.chartProp = chartsDrawer.calcProp;
|
||
this.cChartDrawer = chartsDrawer;
|
||
this.cChartSpace = chartsDrawer.cChartSpace;
|
||
}
|
||
}
|
||
|
||
Point3D.prototype = {
|
||
constructor: Point3D,
|
||
|
||
rotate: function (angleOx, angleOy, angleOz) {
|
||
let x = this.x;
|
||
let y = this.y;
|
||
let z = this.z;
|
||
let cosy = Math.cos(angleOy);
|
||
let siny = Math.sin(angleOy);
|
||
let cosx = Math.cos(angleOx);
|
||
let sinx = Math.sin(angleOx);
|
||
let cosz = Math.cos(angleOz);
|
||
let sinz = Math.sin(angleOz);
|
||
|
||
|
||
let newX = cosy * (sinz * y + cosz * x) - siny * z;
|
||
let newY = sinx * (cosy * z + siny * (sinz * y + cosz * x)) + cosx * (cosz * y - sinz * x);
|
||
let newZ = cosx * (cosy * z + siny * (sinz * y + cosz * x)) - sinx * (cosz * y - sinz * x);
|
||
|
||
this.x = newX;
|
||
this.y = newY;
|
||
this.z = newZ;
|
||
|
||
return this;
|
||
},
|
||
|
||
project: function (matrix) {
|
||
//умножаем
|
||
let projectPoint = matrix.multiplyPoint(this);
|
||
|
||
//делим на 4 коэффициэнт
|
||
let newX = projectPoint.x / projectPoint.t;
|
||
let newY = projectPoint.y / projectPoint.t;
|
||
|
||
this.x = newX;
|
||
this.y = newY;
|
||
|
||
return this;
|
||
},
|
||
|
||
offset: function (offsetX, offsetY, offsetZ) {
|
||
this.x = this.x + offsetX;
|
||
this.y = this.y + offsetY;
|
||
this.z = this.z + offsetZ;
|
||
|
||
return this;
|
||
},
|
||
|
||
scale: function (aspectRatioOx, aspectRatioOy, aspectRatioOz) {
|
||
this.x = this.x / aspectRatioOx;
|
||
this.y = this.y / aspectRatioOy;
|
||
this.z = this.z / aspectRatioOz;
|
||
|
||
return this;
|
||
},
|
||
|
||
multiplyPointOnMatrix1: function (matrix) {
|
||
let multiplyMatrix = matrix.multiplyPoint(this);
|
||
this.x = multiplyMatrix.x;
|
||
this.y = multiplyMatrix.y;
|
||
this.z = multiplyMatrix.z;
|
||
}
|
||
};
|
||
|
||
function Matrix4D() {
|
||
this.a11 = 1.0;
|
||
this.a12 = 0.0;
|
||
this.a13 = 0.0;
|
||
this.a14 = 0.0;
|
||
|
||
this.a21 = 0.0;
|
||
this.a22 = 1.0;
|
||
this.a23 = 0.0;
|
||
this.a24 = 0.0;
|
||
|
||
this.a31 = 0.0;
|
||
this.a32 = 0.0;
|
||
this.a33 = 1.0;
|
||
this.a34 = 0.0;
|
||
|
||
this.a41 = 0.0;
|
||
this.a42 = 0.0;
|
||
this.a43 = 0.0;
|
||
this.a44 = 1.0;
|
||
|
||
return this;
|
||
}
|
||
|
||
Matrix4D.prototype.reset = function () {
|
||
this.a11 = 1.0;
|
||
this.a12 = 0.0;
|
||
this.a13 = 0.0;
|
||
this.a14 = 0.0;
|
||
|
||
this.a21 = 0.0;
|
||
this.a22 = 1.0;
|
||
this.a23 = 0.0;
|
||
this.a24 = 0.0;
|
||
|
||
this.a31 = 0.0;
|
||
this.a32 = 0.0;
|
||
this.a33 = 1.0;
|
||
this.a34 = 0.0;
|
||
|
||
this.a41 = 0.0;
|
||
this.a42 = 0.0;
|
||
this.a43 = 0.0;
|
||
this.a44 = 1.0;
|
||
};
|
||
Matrix4D.prototype.multiply = function (m) {
|
||
let res = new Matrix4D();
|
||
|
||
res.a11 = this.a11 * m.a11 + this.a12 * m.a21 + this.a13 * m.a31 + this.a14 * m.a41;
|
||
res.a12 = this.a11 * m.a12 + this.a12 * m.a22 + this.a13 * m.a32 + this.a14 * m.a42;
|
||
res.a13 = this.a11 * m.a13 + this.a12 * m.a23 + this.a13 * m.a33 + this.a14 * m.a43;
|
||
res.a14 = this.a11 * m.a14 + this.a12 * m.a24 + this.a13 * m.a34 + this.a14 * m.a44;
|
||
|
||
res.a21 = this.a21 * m.a11 + this.a22 * m.a21 + this.a23 * m.a31 + this.a24 * m.a41;
|
||
res.a22 = this.a21 * m.a12 + this.a22 * m.a22 + this.a23 * m.a32 + this.a24 * m.a42;
|
||
res.a23 = this.a21 * m.a13 + this.a22 * m.a23 + this.a23 * m.a33 + this.a24 * m.a43;
|
||
res.a24 = this.a21 * m.a14 + this.a22 * m.a24 + this.a23 * m.a34 + this.a24 * m.a44;
|
||
|
||
res.a31 = this.a31 * m.a11 + this.a32 * m.a21 + this.a33 * m.a31 + this.a34 * m.a41;
|
||
res.a32 = this.a31 * m.a12 + this.a32 * m.a22 + this.a33 * m.a32 + this.a34 * m.a42;
|
||
res.a33 = this.a31 * m.a13 + this.a32 * m.a23 + this.a33 * m.a33 + this.a34 * m.a43;
|
||
res.a34 = this.a31 * m.a14 + this.a32 * m.a24 + this.a33 * m.a34 + this.a34 * m.a44;
|
||
|
||
res.a41 = this.a41 * m.a11 + this.a42 * m.a21 + this.a43 * m.a31 + this.a44 * m.a41;
|
||
res.a42 = this.a41 * m.a12 + this.a42 * m.a22 + this.a43 * m.a32 + this.a44 * m.a42;
|
||
res.a43 = this.a41 * m.a13 + this.a42 * m.a23 + this.a43 * m.a33 + this.a44 * m.a43;
|
||
res.a44 = this.a41 * m.a14 + this.a42 * m.a24 + this.a43 * m.a34 + this.a44 * m.a44;
|
||
|
||
return res;
|
||
};
|
||
Matrix4D.prototype.multiplyPoint = function (p) {
|
||
let res = new Point3D();
|
||
|
||
res.x = p.x * this.a11 + p.y * this.a21 + p.z * this.a31 + this.a41;
|
||
res.y = p.x * this.a12 + p.y * this.a22 + p.z * this.a32 + this.a42;
|
||
res.z = p.x * this.a13 + p.y * this.a23 + p.z * this.a33 + this.a43;
|
||
res.t = p.x * this.a14 + p.y * this.a24 + p.z * this.a34 + this.a44;
|
||
|
||
return res;
|
||
};
|
||
|
||
|
||
//sort parallalepiped faces
|
||
function CSortFaces(cChartDrawer, centralViewPoint) {
|
||
this.cChartDrawer = cChartDrawer;
|
||
this.chartProp = cChartDrawer.calcProp;
|
||
this.centralViewPoint = null;
|
||
this._initProperties(centralViewPoint)
|
||
}
|
||
|
||
CSortFaces.prototype = {
|
||
constructor: CSortFaces,
|
||
|
||
_initProperties: function (centralViewPoint) {
|
||
if (!centralViewPoint) {
|
||
let top = this.chartProp.chartGutter._top;
|
||
let bottom = this.chartProp.chartGutter._bottom;
|
||
let left = this.chartProp.chartGutter._left;
|
||
let right = this.chartProp.chartGutter._right;
|
||
|
||
let widthCanvas = this.chartProp.widthCanvas;
|
||
let heightCanvas = this.chartProp.heightCanvas;
|
||
let heightChart = heightCanvas - top - bottom;
|
||
let widthChart = widthCanvas - left - right;
|
||
|
||
let centerChartY = top + heightChart / 2;
|
||
let centerChartX = left + widthChart / 2;
|
||
|
||
let diffX = centerChartX;
|
||
let diffY = centerChartY;
|
||
let diffZ = -1 / this.cChartDrawer.processor3D.rPerspective;
|
||
//TODO протестировать на bar и затем сделать для всех перспективных диаграмм данный сдвиг
|
||
if (!this.cChartDrawer.processor3D.view3D.getRAngAx() && this.chartProp.type === AscFormat.c_oChartTypes.Bar) {
|
||
diffX -= this.cChartDrawer.processor3D.cameraDiffX;
|
||
diffY -= this.cChartDrawer.processor3D.cameraDiffY;
|
||
diffZ -= this.cChartDrawer.processor3D.cameraDiffZ;
|
||
}
|
||
|
||
//TODO пересмотреть правку!
|
||
if (diffZ > 0 && this.chartProp.type === AscFormat.c_oChartTypes.Bar && this.cChartDrawer.processor3D.view3D.getRAngAx() &&
|
||
(this.chartProp.subType === "stackedPer" || this.chartProp.subType === "stacked")) {
|
||
diffZ -= 500;
|
||
}
|
||
|
||
this.centralViewPoint = {x: diffX, y: diffY, z: diffZ};
|
||
} else {
|
||
this.centralViewPoint = centralViewPoint;
|
||
}
|
||
},
|
||
|
||
sortParallelepipeds: function (parallelepipeds) {
|
||
if (!parallelepipeds) {
|
||
return null;
|
||
}
|
||
let intersectionsParallelepipeds = this._getIntersectionsParallelepipeds(parallelepipeds);
|
||
let revIntersections = intersectionsParallelepipeds.reverseIntersections;
|
||
let countIntersection = intersectionsParallelepipeds.countIntersection;
|
||
|
||
let startIndexes = [];
|
||
for (let i = 0; i < countIntersection.length; i++) {
|
||
if (countIntersection[i] === 0) {
|
||
startIndexes.push({index: parseInt(i)});
|
||
}
|
||
}
|
||
|
||
if (startIndexes.length === 0) {
|
||
//TODO сделано для графиков типа stacked, когда пересечения найдены всех параллалеп.
|
||
return this._getSortZIndexArray(parallelepipeds);
|
||
}
|
||
|
||
let g = revIntersections;
|
||
let color = {}; // цвет вершины (0, 1, или 2)
|
||
let time_in = {}, time_out = {}; // "времена" захода и выхода из вершины
|
||
let dfs_timer = 0;
|
||
|
||
let dfs = function (v) {
|
||
time_in[v] = dfs_timer++;
|
||
color[v] = 1;
|
||
|
||
for (let i in g[v]) {
|
||
if (!color[i]) {
|
||
dfs(i);
|
||
}
|
||
}
|
||
|
||
color[v] = 2;
|
||
time_out[v] = dfs_timer++;
|
||
};
|
||
let getMax = function () {
|
||
let max = 0;
|
||
let res = null;
|
||
for (let i in time_out) {
|
||
if (!addIndexes[i] && time_out[i] > max) {
|
||
max = time_out[i];
|
||
res = i;
|
||
}
|
||
}
|
||
return res;
|
||
};
|
||
|
||
for (let i = 0; i < startIndexes.length; i++) {
|
||
dfs(startIndexes[i].index);
|
||
}
|
||
|
||
let addIndexes = {};
|
||
let res = [];
|
||
while (true) {
|
||
let index = getMax();
|
||
|
||
if (null === index) {
|
||
break;
|
||
}
|
||
|
||
res.push({nextIndex: index});
|
||
addIndexes[index] = 1;
|
||
}
|
||
if (res.length < parallelepipeds.length) {
|
||
return this._getSortZIndexArray(parallelepipeds);
|
||
}
|
||
|
||
return res.reverse();
|
||
},
|
||
|
||
_getSortZIndexArray: function (arr) {
|
||
arr.sort(function sortArr(a, b) {
|
||
return b.z - a.z;
|
||
});
|
||
let result = [];
|
||
for (let i = 0; i < arr.length; i++) {
|
||
result.push({nextIndex: i});
|
||
}
|
||
return result;
|
||
},
|
||
|
||
_getIntersectionsParallelepipeds: function (parallelepipeds) {
|
||
//TODO нужно по максимуму оптимизировать, при большом количестве значений работает медленно
|
||
let usuallyIntersect = {};
|
||
let usuallyIntersectRev = {};
|
||
|
||
let intersections = [];
|
||
let reverseIntersections = [];
|
||
let countIntersection = [];
|
||
for (let i = 0; i < parallelepipeds.length; i++) {
|
||
//из каждой точки данного параллалепипеда строим прямые до точки наблюдателя
|
||
let fromParallalepiped = parallelepipeds[i];
|
||
countIntersection[i] = 0;
|
||
|
||
for (let m = 0; m < parallelepipeds.length; m++) {
|
||
if (m === i || usuallyIntersect[i] === m || usuallyIntersectRev[i] === m) {
|
||
continue;
|
||
}
|
||
if (parallelepipeds[m].isValZero && this.cChartDrawer.calcProp.subType !== "normal") {
|
||
continue;
|
||
}
|
||
|
||
for (let l = 0; l < fromParallalepiped.arrPoints.length; l++) {
|
||
//перебираем точки параллалепипеда FROM
|
||
let point = fromParallalepiped.arrPoints[l];
|
||
|
||
//перебираем грани параллалепипеда TO и проверяем на пересечения с прямыми из параллалепипеда FROM
|
||
let toParallalepiped = parallelepipeds[m];
|
||
for (let n = 0; n < toParallalepiped.faces.length; n++) {
|
||
let toVerge = toParallalepiped.faces[n];
|
||
let lineEqucation = this.cChartDrawer.getLineEquation(point, this.centralViewPoint);
|
||
let intersection = this._isIntersectionFaceAndLine(toVerge, lineEqucation, point);
|
||
if (intersection) {
|
||
usuallyIntersect[i] = m;
|
||
usuallyIntersectRev[m] = i;
|
||
|
||
if (!intersections[i]) {
|
||
intersections[i] = [];
|
||
}
|
||
|
||
if (!reverseIntersections[m]) {
|
||
reverseIntersections[m] = [];
|
||
}
|
||
|
||
countIntersection[i]++;
|
||
|
||
intersections[i][m] = 1;
|
||
reverseIntersections[m][i] = 1;
|
||
|
||
l = point.length;
|
||
//console.log("fromParallalepiped: " + i + " toParallalepiped " + m + " x: " + intersection.x + " y: " + intersection.y + " z: " + intersection.z);
|
||
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return {
|
||
intersections: intersections, reverseIntersections: reverseIntersections, countIntersection: countIntersection
|
||
};
|
||
},
|
||
|
||
//смотрим есть ли пересечения точек, выходящих из вершин данной грани, с другими гранями
|
||
_isIntersectionFacesPointLines: function (plainVerge, i, sortZIndexPaths) {
|
||
let res = false;
|
||
let t = this;
|
||
|
||
for (let j = 0; j < plainVerge.points.length; j++) {
|
||
let pointFromVerge = plainVerge.points[j];
|
||
let lineEqucation = t.cChartDrawer.getLineEquation(pointFromVerge, this.centralViewPoint);
|
||
|
||
//пересечение грани и прямой
|
||
if (t._isIntersectionFacesAndLine(lineEqucation, pointFromVerge, i, j, sortZIndexPaths)) {
|
||
res = true;
|
||
break;
|
||
}
|
||
}
|
||
|
||
return res;
|
||
},
|
||
|
||
//пересечение прямой с другими гранями
|
||
_isIntersectionFacesAndLine: function (lineEqucation, pointFromVerge, i, j, sortZIndexPaths) {
|
||
let res = false;
|
||
|
||
for (let k = 0; k < sortZIndexPaths.length; k++) {
|
||
if (k === i) {
|
||
continue;
|
||
}
|
||
|
||
if (this._isIntersectionFaceAndLine(sortZIndexPaths[k], lineEqucation, pointFromVerge, i, j, k)) {
|
||
res = true;
|
||
break;
|
||
}
|
||
}
|
||
|
||
return res;
|
||
},
|
||
|
||
//пересечение прямой гранью
|
||
_isIntersectionFaceAndLine: function (plain, lineEquation, pointFromVerge) {
|
||
let res = false;
|
||
let t = this;
|
||
|
||
//get intersection
|
||
let nIntersectionPlainAndLine = t.cChartDrawer.isIntersectionPlainAndLine(plain.plainEquation, lineEquation);
|
||
|
||
if (null === nIntersectionPlainAndLine) {
|
||
return res;
|
||
}
|
||
|
||
let iSX = nIntersectionPlainAndLine.x;
|
||
let iSY = nIntersectionPlainAndLine.y;
|
||
let iSZ = nIntersectionPlainAndLine.z;
|
||
|
||
if (Math.round(iSZ * 1000) / 1000 < Math.round(pointFromVerge.z * 1000) / 1000) {
|
||
let minMaxpoints = t.cChartDrawer.getMinMaxPoints(plain.points);
|
||
let minX = minMaxpoints.minX, maxX = minMaxpoints.maxX, minY = minMaxpoints.minY, maxY = minMaxpoints.maxY, minZ = minMaxpoints.minZ, maxZ = minMaxpoints.maxZ;
|
||
|
||
let isBeetwenX = t._isBetweenPoint(iSX, minX, maxX);
|
||
let isBeetwenY = t._isBetweenPoint(iSY, minY, maxY);
|
||
let isBeetwenZ = t._isBetweenPoint(iSZ, minZ, maxZ);
|
||
|
||
if (isBeetwenX && isBeetwenY && isBeetwenZ) {
|
||
let point0 = plain.points2[0];
|
||
let point1 = plain.points2[1];
|
||
let point2 = plain.points2[2];
|
||
let point3 = plain.points2[3];
|
||
|
||
let projectIntersection = nIntersectionPlainAndLine;
|
||
if (!this.cChartDrawer.processor3D.view3D.getRAngAx()) {
|
||
projectIntersection =
|
||
t.cChartDrawer._convertAndTurnPoint(nIntersectionPlainAndLine.x, nIntersectionPlainAndLine.y, nIntersectionPlainAndLine.z, true, true);
|
||
}
|
||
|
||
let areaQuadrilateral = plain.plainArea;
|
||
let areaTriangle1 = t.cChartDrawer.getAreaTriangle(point0, projectIntersection, point1);
|
||
let areaTriangle2 = t.cChartDrawer.getAreaTriangle(point1, projectIntersection, point2);
|
||
let areaTriangle3 = t.cChartDrawer.getAreaTriangle(point2, projectIntersection, point3);
|
||
let areaTriangle4 = t.cChartDrawer.getAreaTriangle(point3, projectIntersection, point0);
|
||
|
||
if (parseInt(areaQuadrilateral) === parseInt(areaTriangle1 + areaTriangle2 + areaTriangle3 + areaTriangle4)) {
|
||
//let pointFromVergeProject = t.cChartDrawer._convertAndTurnPoint(pointFromVerge.x, pointFromVerge.y, pointFromVerge.z, true, true);
|
||
//console.log("x: " + projectIntersection.x + " ;y: " + projectIntersection.y + " ;fromX:" + pointFromVergeProject.x + " ;fromY:" + pointFromVergeProject.y);
|
||
|
||
res = nIntersectionPlainAndLine;
|
||
}
|
||
}
|
||
}
|
||
|
||
return res;
|
||
},
|
||
|
||
_isBetweenPoint: function (point, start, end) {
|
||
//TODO округление пересмотреть
|
||
let res = false;
|
||
point = Math.round(point * 100) / 100;
|
||
start = Math.round(start * 100) / 100;
|
||
end = Math.round(end * 100) / 100;
|
||
|
||
if (point >= start && point <= end) {
|
||
res = true;
|
||
}
|
||
|
||
return res;
|
||
},
|
||
|
||
_isEqualPoints: function (point1, point2) {
|
||
//TODO округление пересмотреть
|
||
let res = false;
|
||
|
||
if (parseInt(point1.x) === parseInt(point2.x) && parseInt(point1.y) === parseInt(point2.y) && parseInt(point1.y) === parseInt(point2.y)) {
|
||
res = true;
|
||
}
|
||
|
||
return res;
|
||
}
|
||
};
|
||
|
||
//----------------------------------------------------------export----------------------------------------------------
|
||
window['AscFormat'] = window['AscFormat'] || {};
|
||
window['AscFormat'].Processor3D = Processor3D;
|
||
window['AscFormat'].Point3D = Point3D;
|
||
window['AscFormat'].CSortFaces = CSortFaces;
|
||
window['AscFormat'].global3DPersperctive = global3DPersperctive;
|
||
window['AscFormat'].globalBasePercent = globalBasePercent;
|
||
window['AscCommon'].c_oChartFloorPosition = c_oChartFloorPosition;
|
||
})(window);
|