Хотел бы дополнить предыдущую инструкцию несколькими процедурами для легкого вычисления всех необходимых переменных:
1) Углы между Нормалями по координатам векторов - нужно для задания углов поворота. особенно для Джумбле-головоломок
2) координаты Нормалей по координатам точек на плоскости - нужно для задания осей вращения граней
3) Расстояние до плоскости - нужно для задания глубины сечения
4) координаты Перпендикуляра к ребру по координатам точек на линии - нужно для задания осей вращения ребер
---------------------------------------------------------------------------------------
Каждому, кто хочет создавать новые головоломки, рекомендую изучить скрипт Jumball.xml
В этой головоломке все параметры (координаты нормалей, глубина сечения и углы поворота) рассчитываются с помощью специальных функций!
Они сделаны Борисом, и их можно использовать в любом головоломке

Координаты вершин и формулы для их расчета я взял здесь:
http://dmccooey.com/polyhedra/6TruncatedTriakisTetrahedron2.htmlЭто первая трудная головоломка, у которой для расчета параметров я не использовал SolidWorks !!!
Это идеальный вариант Life-Hack для головоломок!
Вот полезные скрипты:
1) функция Angle - Вычисляет угол вращения от оси 2, до оси 3, вокруг оси 1
function Angle(x1, y1, z1, x2, y2, z2, x3, y3, z3);
begin
vx := y1 * z2 - y2 * z1;
vy := z1 * x2 - z2 * x1;
vz := x1 * y2 - x2 * y1;
wx := y1 * z3 - y3 * z1;
wy := z1 * x3 - z3 * x1;
wz := x1 * y3 - x3 * y1;
Result := ArcCos((vx*wx + vy*wy + vz*wz) / (vx^2 + vy^2 + vz^2));
end;
function Angle2(i1, i2, i3);
begin
vx := ay[i1] * az[i2] - ay[i2] * az[i1];
vy := az[i1] * ax[i2] - az[i2] * ax[i1];
vz := ax[i1] * ay[i2] - ax[i2] * ay[i1];
wx := ay[i1] * az[i3] - ay[i3] * az[i1];
wy := az[i1] * ax[i3] - az[i3] * ax[i1];
wz := ax[i1] * ay[i3] - ax[i3] * ay[i1];
Result := ArcCos((vx*wx + vy*wy + vz*wz) / (vx^2 + vy^2 + vz^2));
end;
далее в скрипте вставляем такой код расчета
// Calc all Jumble Angle
A1 := Angle(px[0], py[0], pz[0], px[1], py[1], pz[1], px[2], py[2], pz[2]);
A2 := Angle(px[0], py[0], pz[0], px[1], py[1], pz[1], px[6], py[6], pz[6]);
/////////
<Axes TurningAngles = "2*Pi" AvailableAngles = "-A2;-A1; 0; A1;A2" PlaneDistances = "D" FixedLayers = "0">
2) процедура Normal - // Вычисляет Нормаль к плоскости по 3м точкам. Возвращает координаты в nx, ny, nz
procedure Normal(x1, y1, z1, x2, y2, z2, x3, y3, z3, i, nn);
begin
nx := (y1-y3) * (z2-z3) - (y2-y3) * (z1-z3);
ny := (z1-z3) * (x2-x3) - (z2-z3) * (x1-x3);
nz := (x1-x3) * (y2-y3) - (x2-x3) * (y1-y3);
// normalize vector
dn := sqrt(nx^2 + ny^2 + nz^2);
nx := nx / dn; ny := ny / dn; nz := nz / dn;
px[i] := nx * nn; py[i] := ny * nn; pz[i] := nz * nn;
// distace to plane
L := x1*nx + y1*ny + z1* nz;
end;
procedure Normal2(i1, i2, i3);
begin
nx := (y[i1]-y[i3]) * (z[i2]-z[i3]) - (y[i2]-y[i3]) * (z[i1]-z[i3]);
ny := (z[i1]-z[i3]) * (x[i2]-x[i3]) - (z[i2]-z[i3]) * (x[i1]-x[i3]);
nz := (x[i1]-x[i3]) * (y[i2]-y[i3]) - (x[i2]-x[i3]) * (y[i1]-y[i3]);
// normalize vector
dn := sqrt(nx^2 + ny^2 + nz^2);
nx := nx / dn; ny := ny / dn; nz := nz / dn;
end;
далее в скрипте вставляем такой код расчета
// Calc all Normal and fill arrays Px,Py,Pz
Normal( C2,-C2, C2, C3,-C0, C3, C1, C1, C4, 0, 1);
Normal( C2,-C2, C2, C0,-C3, C3,-C1,-C4, C1, 1, 1);
////////////
<Axis NormVector = " px[0]; py[0]; pz[0]" />
<Axis NormVector = " px[1]; py[1]; pz[1]" />
Я также использую эту процедуру для вычисления глубины сечения
// Calc cutting distance
Normal(-C3, C0, C3,-C1,-C4, C1, C4, C1, C1,12, 1);
D := L;
/////////////////////
<Axes TurningAngles = "2*Pi" AvailableAngles = "-A2;-A1; 0; A1;A2" PlaneDistances = "D" FixedLayers = "0">
Чтобы рассчитать параметры Edge-головоломок, я рекомендую использовать эту процедуру
3) процедура Perpendicular - Вычисляет перпендикулярную-нормаль к Ребру по 2 точкам.Возвращает координаты в nx, ny, nz, и L - расстояние
procedure Perpendicular(x1, y1, z1, x2, y2, z2, i, nn);
begin
// find third point
x3 := y1 * z2 - y2 * z1 + x1;
y3 := z1 * x2 - z2 * x1 + y1;
z3 := x1 * y2 - x2 * y1 + z1;
nx := (y1-y3) * (z2-z3) - (y2-y3) * (z1-z3);
ny := (z1-z3) * (x2-x3) - (z2-z3) * (x1-x3);
nz := (x1-x3) * (y2-y3) - (x2-x3) * (y1-y3);
// normalize vector
dn := sqrt(nx^2 + ny^2 + nz^2);
nx := nx / dn; ny := ny / dn; nz := nz / dn;
px[i] := nx * nn; py[i] := ny * nn; pz[i] := nz * nn;
// distace to Line
L := x1*nx + y1*ny + z1* nz;
end;
далее в скрипте вставляем такой код расчета
// Calc all Perpendicular and fill arrays Px,Py,Pz
Perpendicular( C2,-C2, C2, C3,-C0, C3, 0, 1);
Perpendicular( C2,-C2, C2, C0,-C3, C3, 1, 1);
// Calc cutting distance
Perpendicular(-C3, C0, C3,-C1,-C4, C1,12, 1);
D := L;
///////////
<Axis NormVector = " px[0]; py[0]; pz[0]" />
<Axis NormVector = " px[1]; py[1]; pz[1]" />
<Axes TurningAngles = "2*Pi" AvailableAngles = "-A2;-A1; 0; A1;A2" PlaneDistances = "D" FixedLayers = "0">
Удачи
