Как и предполагалось в других комментариях, вы, скорее всего, запутались в прогнозах и гониометрии. Существует также более безопасный способ без гониометрии с использованием векторной математики (линейной алгебры).
создать матрицу преобразования m0
, представляющую выровненную плоскость по первому треугольнику t0
под выровненным я имею в виду, что одно из ребер треугольника должно лежать в одном из плоских базисных векторов. Это просто, вы просто задаете один базисный вектор как рассматриваемое ребро, начинаете как одну из его точек и используете перекрестное произведение, чтобы получить остальные векторы.
, поэтому, если у нашего треугольника есть точки p0,p1,p2
, а наши базисные векторы x,y,z
с началом o
, тогда:
x = p1-p0; x /= |x|;
y = p2-p0;
z = cross(x,y); z /= |z|;
y = cross(z,x); y /= |y|;
o = p0
поэтому просто введите их в матрицу преобразования (см. Ссылку внизу ответа)
создать матрицу преобразования m1
, представляющую выровненную плоскость по второму треугольнику t1
это то же самое, что и # 1
вычисление конечной матрицы преобразования m
преобразование t1
в t0
это просто:
m = Inverse(m1)*m0
Теперь любую точку из t1
можно выровнять по t0
, просто умножив матрицу m
на точку. Не забудьте использовать однородные координаты, поэтому point(x,y,z,1)
Здесь маленький C ++ / OpenGL пример:
//---------------------------------------------------------------------------
double t0[3][3]= // 1st triangle
{
-0.5,-0.5,-1.2,
+0.5,-0.5,-0.8,
0.0,+0.5,-1.0,
};
double t1[3][3]= // 2nd triangle
{
+0.5,-0.6,-2.1,
+1.5,-0.5,-2.3,
+1.2,+0.3,-2.2,
};
double arot=0.0; // animation angle
//---------------------------------------------------------------------------
void gl_draw() // main rendering code
{
int i;
double m0[16],m1[16],m[16],x[3],y[3],z[3],t2[3][3];
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslated(0.0,0.0,-10.0);
glRotatef(arot,0.0,1.0,0.0);
// render original triangles
glBegin(GL_TRIANGLES);
glColor3f(1.0,0.0,0.0); for (i=0;i<3;i++) glVertex3dv(t0[i]);
glColor3f(0.0,0.0,1.0); for (i=0;i<3;i++) glVertex3dv(t1[i]);
glEnd();
// x,y,z = t0 plane basis vectors
vector_sub(x,t0[1],t0[0]); // x is fisrt edge
vector_one(x,x); // normalized
vector_sub(y,t0[2],t0[0]); // y is last edge
vector_mul(z,x,y); // z = cross(x,y) ... perpendicular vector to x,y
vector_one(z,z);
vector_mul(y,z,x); // y = cross(z,x) ... perpendicular vector to z,x
vector_one(y,y);
// m0 = transform matrix representing t0 plane
m0[ 3]=0.0; for (i=0;i<3;i++) m0[ 0+i]=x[i];
m0[ 7]=0.0; for (i=0;i<3;i++) m0[ 4+i]=y[i];
m0[11]=0.0; for (i=0;i<3;i++) m0[ 8+i]=z[i];
m0[15]=1.0; for (i=0;i<3;i++) m0[12+i]=t0[0][i];
// x,y,z = t1 plane basis vectors
vector_sub(x,t1[1],t1[0]); // x is fisrt edge
vector_one(x,x); // normalized
vector_sub(y,t1[2],t1[0]); // y is last edge
vector_mul(z,x,y); // z = cross(x,y) ... perpendicular vector to x,y
vector_one(z,z);
vector_mul(y,z,x); // y = cross(z,x) ... perpendicular vector to z,x
vector_one(y,y);
// m1 = transform matrix representing t1 plane
m1[ 3]=0.0; for (i=0;i<3;i++) m1[ 0+i]=x[i];
m1[ 7]=0.0; for (i=0;i<3;i++) m1[ 4+i]=y[i];
m1[11]=0.0; for (i=0;i<3;i++) m1[ 8+i]=z[i];
m1[15]=1.0; for (i=0;i<3;i++) m1[12+i]=t1[0][i];
// m = transform t1 -> t0 = Inverse(m1)*m0
matrix_inv(m,m1);
matrix_mul(m,m,m0);
// t2 = transformed t1
for (i=0;i<3;i++) matrix_mul_vector(t2[i],m,t1[i]);
// render transformed triangle
glLineWidth(2.0);
glBegin(GL_LINE_LOOP);
glColor3f(0.0,1.0,0.0); for (i=0;i<3;i++) glVertex3dv(t2[i]);
glLineWidth(1.0);
glEnd();
glFlush();
SwapBuffers(hdc);
}
//---------------------------------------------------------------------------
Я использовал свою собственную матрицу и векторную математику, надеюсь, комментариев будет достаточно, если не увидите:
Для получения информации о матрицах, вы также найдете источники и уравнения для математики, используемые там. Вот превью для моего теста:
Где красный - t0
треугольник, синий - t1
треугольник, а зеленый - m*t1
преобразованный треугольник. Как вы можете видеть, нет необходимости в гониометрии / углах Эйлера. Я поворачиваю материал на arot
, чтобы визуально проверить, действительно ли зеленый треугольник выровнен с синим, чтобы доказать, что я не сделал глупой ошибки.
Теперь неясно, как именно вы хотите выровнять, например, если вы хотите максимальное покрытие или что-то еще, попробуйте все 3 комбинации и запомните лучшую или выровняйте по ближайшим или наибольшим ребрам обоих треугольников и т. Д. *