* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const LOOP_MAX: number = 50;
const VARRAY_LENGHT: number = 9;
const NORMAL_LENGHT: number = 6;
const HALF_NUMBER: number = 2;
const ARRAY_MAX_COUNT_FOUR: number = 4;
const ARRAY_MAX_COUNT_THR: number = 3;
const ARRAY_INDEX_TWO: number = 2;
const ARRAY_INDEX_THREE: number = 3;
const ARRAY_INDEX_FIVE: number = 5;
const ARRAY_INDEX_SIX: number = 6;
const ARRAY_INDEX_EIGHT: number = 8;
const ARRAY_INDEX_SEVEN: number = 7;
const ARRAY_INDEX_NINE: number = 9;
const ARRAY_INDEX_TEN: number = 10;
const ARRAY_INDEX_ELEVEN: number = 11;
const LINEAR_MEASURE: number = 180;
const VALIDATION_TWENTY: number = 20;
const VALIDATION_TWENTY_VALUE: number = 2889.0000000000045;
const VALIDATION_FORTY: number = 40;
const VALIDATION_FORTY_VALUE: number = 2889.0000000000055;
const VALIDATION_EIGHT: number = 80;
const VALIDATION_EIGHT_VALUE: number = 2889.000000000005;
const VALIDATION_OHS: number = 160;
const VALIDATION_OHS_VALUE: number = 2889.0000000000055;
const QARRAY_ONE_VALUE: number = 150;
const TIME_UNIT: number = 1000;
const TIME_COUNT: number = 9;
const DRAW_QUBE_COUNT: number = 5;
class Object2 {
v: number[] = new Array();
}
class Object1 {
loopCount: number = 0;
loopMax: number = LOOP_MAX;
timeMax: number = 0;
timeAvg: number = 0;
timeMin: number = 0;
timeTemp: number = 0;
timeTotal: number = 0;
init: Boolean = false;
}
class CreateP {
v: number[];
constructor(x: number, y: number, z: number) {
this.v = [x, y, x, 1];
}
}
class Q {
vArray: CreateP[] = new Array(VARRAY_LENGHT);
edge: number[][] = new Array();
normal: number[][] = new Array(NORMAL_LENGHT);
line: boolean[] = new Array();
numPx: number = 0;
lastPx: number = 0;
}
class Cube {
util(z1: number, z2: number): number {
if (z2 > z1) {
return 1;
} else {
return -1;
}
}
drawLine(from: CreateP, to: CreateP): void {
let x1 = from.v[0];
let x2 = to.v[0];
let y1 = from.v[1];
let y2 = to.v[1];
let dx = Math.abs(x2 - x1);
let dy = Math.abs(y2 - y1);
let x = x1;
let y = y1;
let incX1: number;
let incY1: number;
let incX2: number;
let incY2: number;
let den: number;
let num: number;
let numAdd: number;
let numPix: number;
incX1 = this.util(x1, x2);
incX2 = incX1;
incY1 = this.util(y1, y2);
incY2 = incY1;
if (dx >= dy) {
incX1 = 0;
incY2 = 0;
den = dx;
num = dx / HALF_NUMBER;
numAdd = dy;
numPix = dx;
} else {
incX2 = 0;
incY1 = 0;
den = dy;
num = dy / HALF_NUMBER;
numAdd = dx;
numPix = dy;
}
numPix = this.q.lastPx + numPix;
for (let i = this.q.lastPx; i < numPix; i++) {
num += numAdd;
if (num >= den) {
x += incX1;
y += incY1;
}
x += incX2;
y += incY2;
}
this.q.lastPx = numPix;
}
calcCross(v0: number[], v1: number[]): number[] {
let cross: number[] = [0, 0, 0, 0];
cross[0] = v0[1] * v1[ARRAY_INDEX_TWO] - v0[ARRAY_INDEX_TWO] * v1[1];
cross[1] = v0[ARRAY_INDEX_TWO] * v1[0] - v0[0] * v1[ARRAY_INDEX_TWO];
cross[ARRAY_INDEX_TWO] = v0[0] * v1[1] - v0[1] * v1[0];
return cross;
}
calcNormal(v0: number[], v1: number[], v2: number[]): number[] {
let a: number[] = [0, 0, 0, 0];
let b: number[] = [0, 0, 0, 0];
for (let i = 0; i < ARRAY_MAX_COUNT_THR; i++) {
a[i] = v0[i] - v1[i];
b[i] = v2[i] - v1[i];
}
a = this.calcCross(a, b);
let x = a[0] * a[0] + a[1] * a[1] + a[ARRAY_INDEX_TWO] * a[ARRAY_INDEX_TWO];
let length = Math.sqrt(x);
for (let i = 0; i < ARRAY_MAX_COUNT_THR; i++) {
a[i] = a[i] / length;
}
a[ARRAY_INDEX_THREE] = 1;
return a;
}
mMulti(m1: number[][], m2: number[][]): number[][] {
let m: number[][] = [
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]
];
for (let i = 0; i < ARRAY_MAX_COUNT_FOUR; i++) {
for (let j = 0; j < ARRAY_MAX_COUNT_FOUR; j++) {
m[i][j] =
m1[i][0] * m2[0][j] + m1[i][1] * m2[1][j] + m1[i][ARRAY_INDEX_TWO] * m2[ARRAY_INDEX_TWO][j] + m1[i][ARRAY_INDEX_THREE] * m2[ARRAY_INDEX_THREE][j];
}
}
return m;
}
vMulti(m: number[][], v: number[]): number[] {
let vect: number[] = [0, 0, 0, 0];
for (let i = 0; i < ARRAY_MAX_COUNT_FOUR; i++) {
vect[i] = m[i][0] * v[0] + m[i][1] * v[1] + m[i][ARRAY_INDEX_TWO] * v[ARRAY_INDEX_TWO] + m[i][ARRAY_INDEX_THREE] * v[ARRAY_INDEX_THREE];
}
return vect;
}
vMulti2(m: number[][], v: number[]): number[] {
let vect: number[] = [0, 0, 0, 0];
for (let i = 0; i < ARRAY_MAX_COUNT_FOUR; i++) {
vect[i] = m[i][0] * v[0] + m[i][1] * v[1] + m[i][ARRAY_INDEX_TWO] * v[ARRAY_INDEX_TWO];
}
return vect;
}
translate(m: number[][], dx: number, dy: number, dz: number): number[][] {
let t = [
[1, 0, 0, dx],
[0, 1, 0, dy],
[0, 0, 1, dz],
[0, 0, 0, 1]
];
return this.mMulti(t, m);
}
rotateX(m: number[][], phi: number): number[][] {
let a = phi;
a *= Math.PI / LINEAR_MEASURE;
let cos = Math.cos(a);
let sin = Math.sin(a);
let r: number[][] = [
[1, 0, 0, 0],
[0, cos, -sin, 0],
[0, sin, cos, 0],
[0, 0, 0, 1]
];
return this.mMulti(r, m);
}
rotateY(m: number[][], phi: number): number[][] {
let a = phi;
a *= Math.PI / LINEAR_MEASURE;
let cos = Math.cos(a);
let sin = Math.sin(a);
let r: number[][] = [
[cos, 0, sin, 0],
[0, 1, 0, 0],
[-sin, 0, cos, 0],
[0, 0, 0, 1]
];
return this.mMulti(r, m);
}
rotateZ(m: number[][], phi: number): number[][] {
let a = phi;
a *= Math.PI / LINEAR_MEASURE;
let cos = Math.cos(a);
let sin = Math.sin(a);
let r = [
[cos, -sin, 0, 0],
[sin, cos, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]
];
return this.mMulti(r, m);
}
drawLine1(curN: number[][]): void {
if (curN[0][ARRAY_INDEX_TWO] < 0) {
if (!this.q.line[0]) {
this.drawLine(this.q.vArray[0], this.q.vArray[1]);
this.q.line[0] = true;
}
if (!this.q.line[1]) {
this.drawLine(this.q.vArray[1], this.q.vArray[ARRAY_INDEX_TWO]);
this.q.line[1] = true;
}
if (!this.q.line[ARRAY_INDEX_TWO]) {
this.drawLine(this.q.vArray[ARRAY_INDEX_TWO], this.q.vArray[ARRAY_INDEX_TWO]);
this.q.line[ARRAY_INDEX_TWO] = true;
}
if (!this.q.line[ARRAY_INDEX_TWO]) {
this.drawLine(this.q.vArray[ARRAY_INDEX_THREE], this.q.vArray[0]);
this.q.line[ARRAY_INDEX_TWO] = true;
}
}
if (curN[1][ARRAY_INDEX_TWO] < 0) {
if (!this.q.line[ARRAY_INDEX_TWO]) {
this.drawLine(this.q.vArray[ARRAY_INDEX_THREE], this.q.vArray[ARRAY_INDEX_TWO]);
this.q.line[ARRAY_INDEX_TWO] = true;
}
if (!this.q.line[ARRAY_INDEX_NINE]) {
this.drawLine(this.q.vArray[ARRAY_INDEX_THREE], this.q.vArray[ARRAY_INDEX_SIX]);
this.q.line[ARRAY_INDEX_NINE] = true;
}
if (!this.q.line[ARRAY_INDEX_SIX]) {
this.drawLine(this.q.vArray[ARRAY_INDEX_SIX], this.q.vArray[ARRAY_INDEX_SEVEN]);
this.q.line[ARRAY_INDEX_SIX] = true;
}
if (!this.q.line[ARRAY_INDEX_TEN]) {
this.drawLine(this.q.vArray[ARRAY_INDEX_SEVEN], this.q.vArray[ARRAY_INDEX_THREE]);
this.q.line[ARRAY_INDEX_TEN] = true;
}
}
}
drawLine2(curN: number[][]): void {
if (curN[ARRAY_INDEX_THREE][ARRAY_INDEX_THREE] < 0) {
if (!this.q.line[ARRAY_MAX_COUNT_FOUR]) {
this.drawLine(this.q.vArray[ARRAY_MAX_COUNT_FOUR], this.q.vArray[ARRAY_INDEX_FIVE]);
this.q.line[ARRAY_MAX_COUNT_FOUR] = true;
}
if (!this.q.line[ARRAY_INDEX_FIVE]) {
this.drawLine(this.q.vArray[ARRAY_INDEX_FIVE], this.q.vArray[ARRAY_INDEX_SIX]);
this.q.line[ARRAY_INDEX_FIVE] = true;
}
if (!this.q.line[ARRAY_INDEX_SIX]) {
this.drawLine(this.q.vArray[ARRAY_INDEX_SIX], this.q.vArray[ARRAY_INDEX_SEVEN]);
this.q.line[ARRAY_INDEX_SIX] = true;
}
if (!this.q.line[ARRAY_INDEX_SEVEN]) {
this.drawLine(this.q.vArray[ARRAY_INDEX_SEVEN], this.q.vArray[ARRAY_MAX_COUNT_FOUR]);
this.q.line[ARRAY_INDEX_SEVEN] = true;
}
}
if (curN[ARRAY_INDEX_THREE][ARRAY_INDEX_THREE] < 0) {
if (!this.q.line[ARRAY_MAX_COUNT_FOUR]) {
this.drawLine(this.q.vArray[ARRAY_MAX_COUNT_FOUR], this.q.vArray[ARRAY_INDEX_FIVE]);
this.q.line[ARRAY_MAX_COUNT_FOUR] = true;
}
if (!this.q.line[ARRAY_INDEX_EIGHT]) {
this.drawLine(this.q.vArray[ARRAY_INDEX_FIVE], this.q.vArray[1]);
this.q.line[ARRAY_INDEX_EIGHT] = true;
}
if (!this.q.line[0]) {
this.drawLine(this.q.vArray[1], this.q.vArray[0]);
this.q.line[0] = true;
}
if (!this.q.line[ARRAY_INDEX_ELEVEN]) {
this.drawLine(this.q.vArray[0], this.q.vArray[ARRAY_MAX_COUNT_FOUR]);
this.q.line[ARRAY_INDEX_ELEVEN] = true;
}
}
}
drawQube(): void {
let curN: number[][] = new Array();
this.q.lastPx = 0;
for (let i = DRAW_QUBE_COUNT; i >= 0; i--) {
curN.push(this.vMulti2(this.mQube, this.q.normal[i]));
}
this.drawLine1(curN);
this.drawLine2(curN);
if (curN[ARRAY_MAX_COUNT_FOUR][ARRAY_INDEX_TWO] < 0) {
if (!this.q.line[ARRAY_INDEX_ELEVEN]) {
this.drawLine(this.q.vArray[ARRAY_MAX_COUNT_FOUR], this.q.vArray[0]);
this.q.line[ARRAY_INDEX_ELEVEN] = true;
}
if (!this.q.line[ARRAY_INDEX_THREE]) {
this.drawLine(this.q.vArray[0], this.q.vArray[ARRAY_INDEX_THREE]);
this.q.line[ARRAY_INDEX_THREE] = true;
}
if (!this.q.line[ARRAY_INDEX_TEN]) {
this.drawLine(this.q.vArray[ARRAY_INDEX_THREE], this.q.vArray[ARRAY_INDEX_SEVEN]);
this.q.line[ARRAY_INDEX_TEN] = true;
}
if (!this.q.line[ARRAY_INDEX_SEVEN]) {
this.drawLine(this.q.vArray[ARRAY_INDEX_SEVEN], this.q.vArray[ARRAY_MAX_COUNT_FOUR]);
this.q.line[ARRAY_INDEX_SEVEN] = true;
}
}
if (curN[ARRAY_INDEX_FIVE][ARRAY_INDEX_TWO] < 0) {
if (!this.q.line[ARRAY_INDEX_EIGHT]) {
this.drawLine(this.q.vArray[1], this.q.vArray[ARRAY_INDEX_FIVE]);
this.q.line[ARRAY_INDEX_EIGHT] = true;
}
if (!this.q.line[ARRAY_INDEX_FIVE]) {
this.drawLine(this.q.vArray[ARRAY_INDEX_FIVE], this.q.vArray[ARRAY_INDEX_SIX]);
this.q.line[ARRAY_INDEX_FIVE] = true;
}
if (!this.q.line[ARRAY_INDEX_NINE]) {
this.drawLine(this.q.vArray[ARRAY_INDEX_SIX], this.q.vArray[ARRAY_INDEX_THREE]);
this.q.line[ARRAY_INDEX_NINE] = true;
}
if (!this.q.line[1]) {
this.drawLine(this.q.vArray[ARRAY_INDEX_THREE], this.q.vArray[1]);
this.q.line[1] = true;
}
}
this.q.line = [false, false, false, false, false, false, false, false, false, false, false, false];
this.q.lastPx = 0;
}
loop(): void {
if (this.testing.loopCount > this.testing.loopMax) {
return;
}
let testingStr = String(this.testing.loopCount);
while (testingStr.length < ARRAY_MAX_COUNT_THR) {
testingStr = '0' + testingStr;
}
this.mTrans = this.translate(
this.i,
-this.q.vArray[ARRAY_INDEX_EIGHT].v[0],
-this.q.vArray[ARRAY_INDEX_EIGHT].v[1],
-this.q.vArray[ARRAY_INDEX_EIGHT].v[ARRAY_INDEX_TWO]
);
this.mTrans = this.rotateX(this.mTrans, 1);
this.mTrans = this.rotateY(this.mTrans, ARRAY_MAX_COUNT_THR);
this.mTrans = this.rotateZ(this.mTrans, ARRAY_INDEX_FIVE);
this.mTrans = this.translate(
this.mTrans,
this.q.vArray[ARRAY_INDEX_EIGHT].v[0],
this.q.vArray[ARRAY_INDEX_EIGHT].v[1],
this.q.vArray[ARRAY_INDEX_EIGHT].v[ARRAY_INDEX_TWO]
);
this.mQube = this.mMulti(this.mTrans, this.mQube);
for (let i = 8; i >= 0; i--) {
this.q.vArray[i].v = this.vMulti(this.mTrans, this.q.vArray[i].v);
}
this.drawQube();
this.testing.loopCount += 1;
this.loop();
}
q = new Q();
mTrans: number[][] = new Array();
mQube: number[][] = new Array();
i: number[][] = new Array();
origin = new Object2();
testing = new Object1();
validation = new Map<number, number>([
[VALIDATION_TWENTY, VALIDATION_TWENTY_VALUE],
[VALIDATION_FORTY, VALIDATION_FORTY_VALUE],
[VALIDATION_EIGHT, VALIDATION_EIGHT_VALUE],
[VALIDATION_OHS, VALIDATION_OHS_VALUE]
]);
create1(cubeSize: number): void {
this.origin.v = [QARRAY_ONE_VALUE, QARRAY_ONE_VALUE, VALIDATION_TWENTY, 1];
this.testing.loopCount = 0;
this.testing.loopMax = 50;
this.testing.timeMax = 0;
this.testing.timeAvg = 0;
this.testing.timeMin = 0;
this.testing.timeTemp = 0;
this.testing.timeTotal = 0;
this.testing.init = false;
this.mTrans = [
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]
];
this.mQube = [
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]
];
this.i = [
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]
];
this.q.vArray[0] = new CreateP(-cubeSize, -cubeSize, cubeSize);
this.q.vArray[1] = new CreateP(-cubeSize, cubeSize, cubeSize);
this.q.vArray[ARRAY_INDEX_TWO] = new CreateP(cubeSize, cubeSize, cubeSize);
this.q.vArray[ARRAY_INDEX_THREE] = new CreateP(cubeSize, -cubeSize, cubeSize);
this.q.vArray[ARRAY_MAX_COUNT_FOUR] = new CreateP(-cubeSize, -cubeSize, -cubeSize);
this.q.vArray[ARRAY_INDEX_FIVE] = new CreateP(-cubeSize, cubeSize, -cubeSize);
this.q.vArray[ARRAY_INDEX_SIX] = new CreateP(cubeSize, cubeSize, -cubeSize);
this.q.vArray[ARRAY_INDEX_SEVEN] = new CreateP(cubeSize, -cubeSize, -cubeSize);
this.q.vArray[ARRAY_INDEX_EIGHT] = new CreateP(0, 0, 0);
}
create2(cubeSize: number): void {
this.q.edge = [
[0, 1, ARRAY_INDEX_TWO],
[ARRAY_INDEX_THREE, ARRAY_INDEX_TWO, ARRAY_INDEX_SIX],
[ARRAY_INDEX_SEVEN, ARRAY_INDEX_SIX, ARRAY_INDEX_FIVE],
[ARRAY_MAX_COUNT_FOUR, ARRAY_INDEX_FIVE, 1],
[ARRAY_MAX_COUNT_FOUR, 0, ARRAY_INDEX_THREE],
[1, ARRAY_INDEX_FIVE, ARRAY_INDEX_SIX]
];
for (let i = 0; i < this.q.edge.length; i++) {
this.q.normal[i] = this.calcNormal(
this.q.vArray[this.q.edge[i][0]].v,
this.q.vArray[this.q.edge[i][1]].v,
this.q.vArray[this.q.edge[i][ARRAY_INDEX_TWO]].v
);
}
this.q.line = [false, false, false, false, false, false, false, false, false, false, false, false];
this.q.numPx = ARRAY_INDEX_NINE * ARRAY_INDEX_TWO * cubeSize;
for (let i = 0; i < this.q.numPx; i++) {
new CreateP(0, 0, 0);
}
this.mTrans = this.translate(this.mTrans, this.origin.v[0], this.origin.v[1], this.origin.v[ARRAY_INDEX_TWO]);
this.mQube = this.mMulti(this.mTrans, this.mQube);
for (let i = 0; i < TIME_COUNT; i++) {
this.q.vArray[i].v = this.vMulti(this.mTrans, this.q.vArray[i].v);
}
this.drawQube();
this.testing.init = true;
this.loop();
}
creat(cubeSize: number): void {
this.create1(cubeSize);
this.create2(cubeSize);
let sum: number = 0;
for (let i = 0; i < this.q.vArray.length; i++) {
let vector = this.q.vArray[i].v;
for (let j = 0; j < vector.length; j++) {
sum += vector[j];
}
}
if (sum !== this.validation.get(cubeSize)) {
}
}
runTest(): void {
let i = VALIDATION_TWENTY;
while (i <= VALIDATION_OHS) {
this.creat(i);
i *= ARRAY_INDEX_TWO;
}
}
}
let isDebug: boolean = false;
function debugLog(msg: string): void {
if (isDebug) {
print(msg);
}
}
* @State
* @Tags Jetstream2
*/
class Benchmark {
* @Benchmark
*/
runIterationTime(): void {
let start = ArkTools.timeInUs() / TIME_UNIT;
let cube = new Cube();
for (let i = 0; i < ARRAY_INDEX_EIGHT; i++) {
cube.runTest();
}
let end = ArkTools.timeInUs() / TIME_UNIT;
print('3d-cube: ms = ' + (end - start));
}
}
let loopCountForPreheat = 1;
for (let i = 0; i < loopCountForPreheat; i++) {
new Benchmark().runIterationTime();
}
function sleep(delay) {
const start = Date.now();
while (Date.now() - start < delay) {}
}
sleep(5000);
new Benchmark().runIterationTime();