geometry = r_a => {
const S = 125;
const [A,B,C,D] = points.map(p => p.slice(0,3));
const atan2v = u => Math.atan2(u[1],u[0]);
const faces = [
{ from: atan2v(A), to: atan2v(B), between: [] },
{ from: atan2v(B), to: atan2v(C), between: [] },
{ from: atan2v(C), to: atan2v(D), between: [] },
{ from: atan2v(D), to: atan2v(A), between: [] },
];
[1/4*PI, 3/4*PI, -3/4*PI, -1/4*PI].map(corner => {
const face = _.find(faces, (face, i) => angle_between(corner, face.from, face.to));
face.between.push(corner);
});
const to_edge = a => {
const u = [cos(a), sin(a), 0];
if (-PI*1/4 <= a && a <= PI*1/4) return scale(S/ cos(a), u);
if ( PI*1/4 <= a && a <= PI*3/4) return scale(S/ sin(a), u);
if ( PI*3/4 <= a || a <= -PI*3/4) return scale(S/-cos(a), u);
if (-PI*3/4 <= a && a <= -PI*1/4) return scale(S/-sin(a), u);
throw `Err @ geometry/to_edge`;
};
for (var nface, face, i = 0; face = faces[i], i < faces.length; i++) {
nface = [[0,0,0], to_edge(face.from)];
face.between.forEach(a => nface.push(to_edge(a)));
nface.push(to_edge(face.to));
faces[i] = nface;
}
faces[1] = rotate(B,-r_b)(faces[1]);
faces[3] = rotate(A,r_a)(faces[3]);
const C2 = faces[2][1] = faces[1][faces[1].length - 1];
const D2 = faces[2][faces[2].length - 1] = faces[3][1];
faces[2].splice(2, faces[2].length - 3);
return { faces };
}