if (y < ymin) {
ymin = y;
} else if (ymax < y) {
ymax = y;
}
if (z < zmin) {
zmin = z;
} else if (zmax < z) {
zmax = z;
}
}
ph.ph$reciprocalMatrix = nScaleXYZ (nNewITranslateXYZ (-xmin, -ymin, -zmin), 1 / (xmax - xmin), 1 / (ymax - ymin), 1 / (zmax - zmin));
}
return ph;
}
function phNewBox (x0, x1, y0, y1, z0, z1, ox0, ox1, oy0, oy1, oz0, oz1) {
let va = [[x0, y0, z0],
[x1, y0, z0],
[x1, y1, z0],
[x0, y1, z0],
[x0, y0, z1],
[x1, y0, z1],
[x1, y1, z1],
[x0, y1, z1]];
let fa = [[0, 4, 7, 3],
[1, 2, 6, 5],
[0, 1, 5, 4],
[2, 3, 7, 6],
[0, 3, 2, 1],
[4, 5, 6, 7]];
let oa = [ox0, ox1, oy0, oy1, oz0, oz1];
return phMakeFields ({
ph$vertexArray: va,
ph$faceArray: fa,
ph$openArray: oa
});
}
function phNewCylinderXY (x, y, r, z0, z1) {
const step = 5;
let va = [];
for (let d = 0; d < 360; d += step) {
let t = rad (d);
va.push ([x + r * cos (t), y + r * sin (t)]);
}
return phNewPolygonXY1 (va, [z0, z1]);
}
function phNewCylinderYZ (y, z, r, x0, x1) {
return phExchangeYZX (phNewCylinderXY (y, z, r, x0, x1));
}
function phNewCylinderZX (z, x, r, y0, y1) {
return phExchangeZXY (phNewCylinderXY (z, x, r, y0, y1));
}
function phNewRegularDodecahedron () {
return phMakeFields ({
ph$vertexArray: [
[1/15*sqrt(150-30*sqrt(5)), 0, 1/15*sqrt(75+30*sqrt(5))],
[1/15*sqrt(75-30*sqrt(5)), 1/3*sqrt(3), 1/15*sqrt(75+30*sqrt(5))],
[-1/30*sqrt(150+30*sqrt(5)), 1/6*sqrt(3)*(sqrt(5)-1), 1/15*sqrt(75+30*sqrt(5))],
[-1/30*sqrt(150+30*sqrt(5)), -1/6*sqrt(3)*(sqrt(5)-1), 1/15*sqrt(75+30*sqrt(5))],
[1/15*sqrt(75-30*sqrt(5)), -1/3*sqrt(3), 1/15*sqrt(75+30*sqrt(5))],
[1/15*sqrt(150+30*sqrt(5)), 0, 1/15*sqrt(75-30*sqrt(5))],
[1/30*sqrt(150-30*sqrt(5)), 1/6*sqrt(3)*(sqrt(5)+1), 1/15*sqrt(75-30*sqrt(5))],
[-1/15*sqrt(75+30*sqrt(5)), 1/3*sqrt(3), 1/15*sqrt(75-30*sqrt(5))],
[-1/15*sqrt(75+30*sqrt(5)), -1/3*sqrt(3), 1/15*sqrt(75-30*sqrt(5))],
[1/30*sqrt(150-30*sqrt(5)), -1/6*sqrt(3)*(sqrt(5)+1), 1/15*sqrt(75-30*sqrt(5))],
[-1/15*sqrt(150+30*sqrt(5)), 0, -1/15*sqrt(75-30*sqrt(5))],
[-1/30*sqrt(150-30*sqrt(5)), 1/6*sqrt(3)*(sqrt(5)+1), -1/15*sqrt(75-30*sqrt(5))],
[1/15*sqrt(75+30*sqrt(5)), 1/3*sqrt(3), -1/15*sqrt(75-30*sqrt(5))],
[1/15*sqrt(75+30*sqrt(5)), -1/3*sqrt(3), -1/15*sqrt(75-30*sqrt(5))],
[-1/30*sqrt(150-30*sqrt(5)), -1/6*sqrt(3)*(sqrt(5)+1), -1/15*sqrt(75-30*sqrt(5))],
[-1/15*sqrt(150-30*sqrt(5)), 0, -1/15*sqrt(75+30*sqrt(5))],
[-1/15*sqrt(75-30*sqrt(5)), 1/3*sqrt(3), -1/15*sqrt(75+30*sqrt(5))],
[1/30*sqrt(150+30*sqrt(5)), 1/6*sqrt(3)*(sqrt(5)-1), -1/15*sqrt(75+30*sqrt(5))],
[1/30*sqrt(150+30*sqrt(5)), -1/6*sqrt(3)*(sqrt(5)-1), -1/15*sqrt(75+30*sqrt(5))],
[-1/15*sqrt(75-30*sqrt(5)), -1/3*sqrt(3), -1/15*sqrt(75+30*sqrt(5))]
],
ph$faceArray: [
[0, 1, 2, 3, 4],
[0, 4, 9, 13, 5],
[0, 5, 12, 6, 1],
[1, 6, 11, 7, 2],
[2, 7, 10, 8, 3],
[3, 8, 14, 9, 4],
[5, 13, 18, 17, 12],
[6, 12, 17, 16, 11],
[7, 11, 16, 15, 10],
[8, 10, 15, 19, 14],
[9, 14, 19, 18, 13],
[15, 16, 17, 18, 19]
]
});
}
function phNewRegularHexahedron () {
return phMakeFields ({
ph$vertexArray: [
[1/3*sqrt(3), 1/3*sqrt(3), 1/3*sqrt(3)],
[-1/3*sqrt(3), 1/3*sqrt(3), 1/3*sqrt(3)],
[-1/3*sqrt(3), -1/3*sqrt(3), 1/3*sqrt(3)],
[1/3*sqrt(3), -1/3*sqrt(3), 1/3*sqrt(3)],
[1/3*sqrt(3), 1/3*sqrt(3), -1/3*sqrt(3)],
[-1/3*sqrt(3), 1/3*sqrt(3), -1/3*sqrt(3)],
[-1/3*sqrt(3), -1/3*sqrt(3), -1/3*sqrt(3)],
[1/3*sqrt(3), -1/3*sqrt(3), -1/3*sqrt(3)]
],
ph$faceArray: [
[0, 1, 2, 3],
[0, 3, 7, 4],
[0, 4, 5, 1],
[1, 5, 6, 2],
[2, 6, 7, 3],
[4, 7, 6, 5]
]
});
}
function phNewRegularIcosahedron () {
return phMakeFields ({
ph$vertexArray: [
[0, 0, 1],
[0, -2/5*sqrt(5), 1/5*sqrt(5)],
[1/10*sqrt(50+10*sqrt(5)), -1/10*(5-sqrt(5)), 1/5*sqrt(5)],
[1/10*sqrt(50-10*sqrt(5)), 1/10*(5+sqrt(5)), 1/5*sqrt(5)],
[-1/10*sqrt(50-10*sqrt(5)), 1/10*(5+sqrt(5)), 1/5*sqrt(5)],
[-1/10*sqrt(50+10*sqrt(5)), -1/10*(5-sqrt(5)), 1/5*sqrt(5)],
[0, 2/5*sqrt(5), -1/5*sqrt(5)],
[1/10*sqrt(50+10*sqrt(5)), 1/10*(5-sqrt(5)), -1/5*sqrt(5)],
[1/10*sqrt(50-10*sqrt(5)), -1/10*(5+sqrt(5)), -1/5*sqrt(5)],
[-1/10*sqrt(50-10*sqrt(5)), -1/10*(5+sqrt(5)), -1/5*sqrt(5)],
[-1/10*sqrt(50+10*sqrt(5)), 1/10*(5-sqrt(5)), -1/5*sqrt(5)],
[0, 0, -1 ]
],
ph$faceArray: [
[0, 1, 2],
[0, 2, 3],
[0, 3, 4],
[0, 4, 5],
[0, 5, 1],
[1, 8, 2],
[2, 7, 3],
[3, 6, 4],
[4, 10, 5],
[5, 9, 1],
[11, 6, 7],
[11, 7, 8],
[11, 8, 9],
[11, 9, 10],
[11, 10, 6],
[6, 3, 7],
[7, 2, 8],
[8, 1, 9],
[9, 5, 10],
[10, 4, 6]
]
});
}
function phNewRegularOctahedron () {
return phMakeFields ({
ph$vertexArray: [
[0, 0, 1],
[1, 0, 0],
[0, 1, 0],
[-1, 0, 0],
[0, -1, 0],
[0, 0, -1]
],
ph$faceArray: [
[0, 1, 2],
[0, 2, 3],
[0, 3, 4],
[0, 4, 1],
[1, 4, 5],
[1, 5, 2],
[2, 5, 3],
[3, 5, 4]
]
});
}
function phNewRegularTetrahedron () {
return phMakeFields ({
ph$vertexArray: [
[0, 0, 1],
[2/3*sqrt(2), 0, -1/3],
[-1/3*sqrt(2), 1/3*sqrt(6), -1/3],
[-1/3*sqrt(2), -1/3*sqrt(6), -1/3]
],
ph$faceArray: [
[0, 1, 2],
[0, 2, 3],
[0, 3, 1],
[1, 3, 2]
]
});
}
function phNewPolygonXY (pg, za) {
let va2 = pg.pg$vertexArray;
let fa2 = pg.pg$faceArray;
let va2l = va2.length;
let fa2l = fa2.length;
let zal = za.length;
let va3 = [];
for (let zai = zal - 1; 0 <= zai; zai--) {
let z = za[zai];
for (let va2i = 0; va2i < va2l; va2i++) {
let v2 = va2[va2i];
va3.push ([v2[0], v2[1], z]);
}
}
let fa3 = [];
let na3 = [];
for (let fa2i = 0; fa2i < fa2l; fa2i++) {
let f2 = fa2[fa2i];
let f2l = f2.length;
let f3 = [];
for (let f2i = 0; f2i < f2l; f2i++) {
f3.push (f2[f2i]);
}
fa3.push (f3);
na3.push ([0, 0, 1]);
}
for (let fa2i = 0; fa2i < fa2l; fa2i++) {
let f2 = fa2[fa2i];
let f2l = f2.length;
let f3 = [];
for (let f2i = f2l - 1; 0 <= f2i; f2i--) {
f3.push (f2[f2i] + va2l * (zal - 1));
}
fa3.push (f3);
na3.push ([0, 0, -1]);
}
for (let zai = 0; zai + 1 < zal; zai++) {
for (let fa2i = 0; fa2i < fa2l; fa2i++) {
let f2 = fa2[fa2i];
let f2l = f2.length;
for (let f2i = 0; f2i < f2l; f2i++) {
let f2i1 = f2i + 1 < f2l ? f2i + 1 : 0;
fa3.push ([f2[f2i] + va2l * zai,
f2[f2i] + va2l * (zai + 1),
f2[f2i1] + va2l * (zai + 1),
f2[f2i1] + va2l * zai]);
let vtl = va2[f2[f2i]];
let vtr = va2[f2[f2i1]];
na3.push ([vtr[1] - vtl[1], vtl[0] - vtr[0], 0]);
}
}
}
for (let fa3i = 0; fa3i + 1 < fa3.length; fa3i++) {
for (let fa3j = fa3i + 1; fa3j < fa3.length; fa3j++) {
if (phIsReversedFace (fa3[fa3i], fa3[fa3j])) {
fa3.splice (fa3j, 1);
na3.splice (fa3j, 1);
fa3.splice (fa3i, 1);
na3.splice (fa3i, 1);
fa3i--;
break;
}
}
}
let ra = [];
for (let va3i = 0; va3i < va3.length; va3i++) {
ra[va3i] = -1;
}
for (let fa3i = 0; fa3i < fa3.length; fa3i++) {
let f3 = fa3[fa3i];
for (let f3i = 0; f3i < f3.length; f3i++) {
ra[f3[f3i]] = 0;
}
}
let n = 0;
for (let va3i = 0; va3i < va3.length; va3i++) {
if (ra[va3i] == 0) {
va3[n] = va3[va3i];
ra[va3i] = n;
n++;
}
}
va3.splice (n, va3.length - n);
for (let fa3i = 0; fa3i < fa3.length; fa3i++) {
let f3 = fa3[fa3i];
for (let f3i = 0; f3i < f3.length; f3i++) {
f3[f3i] = ra[f3[f3i]];
}
}
return phMakeFields ({
ph$vertexArray: va3,
ph$faceArray: fa3,
ph$normalArray: na3
});
}
function phNewPolygonYZ (pg, xa) {
return phExchangeYZX (phNewPolygonXY (pg, xa));
}
function phNewPolygonZX (pg, ya) {
return phExchangeZXY (phNewPolygonXY (pg, ya));
}
function phNewPolygonXY1 (va, za) {
let f = [];
for (let vai = 0; vai < va.length; vai++) {
f.push (vai);
}
return phNewPolygonXY ({ pg$vertexArray: va, pg$faceArray: [f] }, za);
}
function phNewPolygonYZ1 (va, xa) {
let f = [];
for (let vai = 0; vai < va.length; vai++) {
f.push (vai);
}
return phNewPolygonYZ ({ pg$vertexArray: va, pg$faceArray: [f] }, xa);
}
function phNewPolygonZX1 (va, ya) {
let f = [];
for (let vai = 0; vai < va.length; vai++) {
f.push (vai);
}
return phNewPolygonZX ({ pg$vertexArray: va, pg$faceArray: [f] }, ya);
}
function phNewArcXY (ox, oy, ri, ro, t0, t1, z0, z1, ot0, ot1, oz0, oz1) {
const step = rad (5);
let n = max2 (1, roundn ((t1 - t0) / step));
let th = (t1 - t0) / (2 * n);
let xi = ri * cos (th);
let yi = ri * sin (th);
let xo = ro * cos (th);
let yo = ro * sin (th);
let pha = [];
for (let k = 0; k < n; k++) {
let va = [[xo, yo, z0],
[xi, yi, z0],
[xi, -yi, z0],
[xo, -yo, z0],
[xo, yo, z1],
[xi, yi, z1],
[xi, -yi, z1],
[xo, -yo, z1]];
let fa = [[1, 2, 6, 5],
[3, 0, 4, 7]];
let oa = [0,
0];
if (k == 0) {
fa.push ([3, 2, 6, 7]);
oa.push (ot0);
} else if (k == n - 1) {
fa.push ([0, 1, 5, 4]);
oa.push (ot1);
}
fa.push ([1, 0, 3, 2]);
oa.push (oz0);
fa.push ([4, 5, 6, 7]);
oa.push (oz1);
let ph = phNew (va, fa, oa);
phRotateXY (ph, t0 + (2 * k + 1) * th);
phTranslateXYZ (ph, ox, oy, 0);
pha.push (ph);
}
return pha;
}
function phNewArcYZ (oy, oz, ri, ro, t0, t1, x0, x1, c0, c1, d0, d1) {
let pha = phNewArcXY (oy, oz, ri, ro, t0, t1, x0, x1, c0, c1, d0, d1);
for (let i = 0; i < pha.length; i++) {
phExchangeYZX (pha[i]);
}
return pha;
}
function phNewArcZX (oz, ox, ri, ro, t0, t1, y0, y1, c0, c1, d0, d1) {
let pha = phNewArcXY (oz, ox, ri, ro, t0, t1, y0, y1, c0, c1, d0, d1);
for (let i = 0; i < pha.length; i++) {
phExchangeZXY (pha[i]);
}
return pha;
}
function phRotateXY (ph, t) {
let va = ph.ph$vertexArray;
let na = ph.ph$normalArray;
let c = cos (t);
let s = sin (t);
for (let i = 0; i < va.length; i++) {
let v = va[i];
let vx = v[0];
let vy = v[1];
v[0] = c * vx - s * vy;
v[1] = s * vx + c * vy;
}
for (let i = 0; i < na.length; i++) {
let n = na[i];
let nx = n[0];
let ny = n[1];
n[0] = c * nx - s * ny;
n[1] = s * nx + c * ny;
}
ph.ph$reciprocalMatrix = nNewConcatenate (nNewIRotateXY (-t), ph.ph$reciprocalMatrix);
return ph;
}
function phRotateYZ (ph, t) {
let va = ph.ph$vertexArray;
let na = ph.ph$normalArray;
let c = cos (t);
let s = sin (t);
for (let i = 0; i < va.length; i++) {
let v = va[i];
let vy = v[1];
let vz = v[2];
v[1] = c * vy - s * vz;
v[2] = s * vy + c * vz;
}
for (let i = 0; i < na.length; i++) {
let n = na[i];
let ny = n[1];
let nz = n[2];
n[1] = c * ny - s * nz;
n[2] = s * ny + c * nz;
}
ph.ph$reciprocalMatrix = nNewConcatenate (nNewIRotateYZ (-t), ph.ph$reciprocalMatrix);
return ph;
}
function phRotateZX (ph, t) {
let va = ph.ph$vertexArray;
let na = ph.ph$normalArray;
let c = cos (t);
let s = sin (t);
for (let i = 0; i < va.length; i++) {
let v = va[i];
let vz = v[2];
let vx = v[0];
v[2] = c * vz - s * vx;
v[0] = s * vz + c * vx;
}
for (let i = 0; i < na.length; i++) {
let n = na[i];
let nz = n[2];
let nx = n[0];
n[2] = c * nz - s * nx;
n[0] = s * nz + c * nx;
}
ph.ph$reciprocalMatrix = nNewConcatenate (nNewIRotateZX (-t), ph.ph$reciprocalMatrix);
return ph;
}
function phScaleXYZ (ph, s, t, u) {
let va = ph.ph$vertexArray;
for (let i = 0; i < va.length; i++) {
let v = va[i];
v[0] *= s;
v[1] *= t;
v[2] *= u;
}
ph.ph$reciprocalMatrix = nNewConcatenate (nNewIScaleXYZ (1 / s, 1 / t, 1 / u), ph.ph$reciprocalMatrix);
if (!(s == t && s == u)) {
ph.ph$normalArray = null;
phMakeFields (ph);
}
return ph;
}
function phTranslateXYZ (ph, s, t, u) {
let va = ph.ph$vertexArray;
for (let i = 0; i < va.length; i++) {
let v = va[i];
v[0] += s;
v[1] += t;
v[2] += u;
}
ph.ph$reciprocalMatrix = nNewConcatenate (nNewITranslateXYZ (-s, -t, -u), ph.ph$reciprocalMatrix);
return ph;
}
function phLetCopy (ph2, ph1) {
let va1 = ph1.ph$vertexArray;
let fa1 = ph1.ph$faceArray;
let oa1 = ph1.ph$openArray;
let na1 = ph1.ph$normalArray;
let rm1 = ph1.ph$reciprocalMatrix;
let va2 = [];
for (let i = 0; i < va1.length; i++) {
va2.push (va1[i].concat ());
}
let fa2 = [];
for (let i = 0; i < fa1.length; i++) {
fa2.push (fa1[i].concat ());
}
let oa2 = oa1.concat ();
let na2 = [];
for (let i = 0; i < na1.length; i++) {
na2.push (na1[i].concat ());
}
let rm2 = rm1.concat ();
ph2.ph$vertexArray = va2;
ph2.ph$faceArray = fa2;
ph2.ph$openArray = oa2;
ph2.ph$normalArray = na2;
ph2.ph$reciprocalMatrix = rm2;
return ph2;
}
function phNewCopy (ph1) {
return phLetCopy ({}, ph1);
}
function phExchangeYZX (ph) {
let va = ph.ph$vertexArray;
let na = ph.ph$normalArray;
for (let i = 0; i < va.length; i++) {
let v = va[i];
let t = v[0];
v[0] = v[2];
v[2] = v[1];
v[1] = t;
}
for (let i = 0; i < na.length; i++) {
let n = na[i];
let t = n[0];
n[0] = n[2];
n[2] = n[1];
n[1] = t;
}
nExchangeYZX (ph.ph$reciprocalMatrix);
return ph;
}
function phExchangeZXY (ph) {
let va = ph.ph$vertexArray;
let na = ph.ph$normalArray;
for (let i = 0; i < va.length; i++) {
let v = va[i];
let t = v[0];
v[0] = v[1];
v[1] = v[2];
v[2] = t;
}
for (let i = 0; i < na.length; i++) {
let n = na[i];
let t = n[0];
n[0] = n[1];
n[1] = n[2];
n[2] = t;
}
nExchangeZXY (ph.ph$reciprocalMatrix);
return ph;
}
function phRemoveFace (ph, fn) {
let fa = ph.ph$faceArray;
let oa = ph.ph$openArray;
let na = ph.ph$normalArray;
fa.splice (fn, 1, 0);
oa.splice (fn, 1, 0);
na.splice (fn, 1, 0);
return ph;
}
function phJoin (ph, ph2) {
let va = ph.ph$vertexArray;
let fa = ph.ph$faceArray;
let oa = ph.ph$openArray;
let na = ph.ph$normalArray;
let va2 = ph2.ph$vertexArray;
let fa2 = ph2.ph$faceArray;
let oa2 = ph2.ph$openArray;
let na2 = ph2.ph$normalArray;
let val = va.length;
for (let i = 0; i < va2.length; i++) {
va.push (va2[i].concat ());
}
for (let i = 0; i < fa2.length; i++) {
let ga2 = fa2[i].concat ();
for (let j = 0; j < ga2.length; j++) {
ga2[j] += val;
}
fa.push (ga2);
oa.push (oa2[i]);
na.push (na2[i].concat ());
}
for (let i = 0; i + 1 < va.length; i++) {
for (let j = i + 1; j < va.length; j++) {
if (phIsSameVertex (va[i], va[j])) {
for (let k = 0; k < fa.length; k++) {
let f = fa[k];
for (let l = 0; l < f.length; l++) {
if (f[l] == j) {
f[l] = i;
} else if (j < f[l]) {
f[l]--;
}
}
}
va.splice (j, 1);
j--;
}
}
}
for (let i = 0; i + 1 < fa.length; i++) {
for (let j = i + 1; j < fa.length; j++) {
if (phIsSameFace (fa[i], fa[j])) {
fa.splice (j, 1);
oa.splice (j, 1);
na.splice (j, 1);
j--;
}
}
}
for (let i = 0; i + 1 < fa.length; i++) {
for (let j = i + 1; j < fa.length; j++) {
if (phIsReversedFace (fa[i], fa[j])) {
fa.splice (j, 1);
oa.splice (j, 1);
na.splice (j, 1);
fa.splice (i, 1);
oa.splice (i, 1);
na.splice (i, 1);
i--;
break;
}
}
}
ph.ph$reciprocalMatrix = null;
phMakeFields (ph);
return ph;
}
function phSplitXL (ph, x0, x1, l) {
while (3 * l <= x1 - x0) {
x0 += l;
x1 -= l;
phSplitX (ph, x0);
phSplitX (ph, x1);
}
if (2 * l <= x1 - x0) {
phSplitX (ph, (x0 + x1) * 0.5);
}
return ph;
}
function phSplitYL (ph, y0, y1, l) {
while (3 * l <= y1 - y0) {
y0 += l;
y1 -= l;
phSplitY (ph, y0);
phSplitY (ph, y1);
}
if (2 * l <= y1 - y0) {
phSplitY (ph, (y0 + y1) * 0.5);
}
return ph;
}
function phSplitZL (ph, z0, z1, l) {
while (3 * l <= z1 - z0) {
z0 += l;
z1 -= l;
phSplitZ (ph, z0);
phSplitZ (ph, z1);
}
if (2 * l <= z1 - z0) {
phSplitZ (ph, (z0 + z1) * 0.5);
}
return ph;
}