Задачки любителям 3Д
Для Z=0 действительно просто. Только немного не так как Вы написали.
У меня получается два подобных прямоугольных треугольника.
Один с гипотенузой "линией" и второй с гипотенузой "перемещения"
С первого находим угол, со второго две стороны: dx,dy
И затем просто перемещаем линию.
Теперь осталось Z добавить.
То, что я написал, легко обобщается и на 3Д:
до момента получения вектора N one doesn't use the explicit coordinates, nor the dimensionality
of the space (so it works in a space of an arbitrary dimension).
So N = (X1 - X2) / |X1 - X2| (vector form!)
Then one takes two arbitrary vectors Y'1 = (x'1, y'1, z'1) and Y2, such that the three vectors N, Y1, Y2 - are linearly independent
(this is almost always the case once one takes random vectors).
Then one starts Gram-Schmidt orthogonalization process taking N as the first vector. One obtains orthonormal vectos N, N1, N2.
Two-parametric surface:
X' (t, alpha) = (X1 - X2) t + X2 +
(a /2) * (N1* cos(alpha) + N2*sin(alpha)) - is a cylinder around your line, with the radius = a/2.
For the fixed parameter alpha - one obtains one of parallel lines, parametrized with t, which is parallel to the initial line, and has the distance = a/2 to it.
Нужен видимо еще какой то вектор указывающий направление, потому как можно целый цилиндр параллельных прямых сделать возле центральной.
Именно. Или соглашение, как расположить басис.
В примере я совмещаю ось х с направлющим вектором заданной линии.
using System.Numerics;
float distance = (float)Math.Sqrt(2);
Vector3 pnt1 = new Vector3(1, 0, 0);
Vector3 pnt2 = new Vector3(4, 3, 0);
Vector3 ray = pnt2 - pnt1;
Matrix4x4 rotate1 = Matrix4x4.CreateRotationX(0.0f); // В результате поворачивает полученную линию вокруг заданной (опционально).
Matrix4x4 rotate2 = getRotateMatrix(Vector3.UnitX, Vector3.Normalize(ray)); // Совмещает ось х с направляющим вектором линии
Matrix4x4 rotate = Matrix4x4.Multiply(rotate1, rotate2); // Комбинация
Vector3 axis = Vector3.Transform(Vector3.UnitY, rotate); // Получаем вектор, вдоль которого будем перемещать линию
Matrix4x4 translate = Matrix4x4.CreateTranslation(distance * axis); // Собственно перемещение
pnt1 = Vector3.Transform(pnt1, translate);
pnt2 = Vector3.Transform(pnt2, translate);
// Матрица поворота одного нормализованного вектора к другому. Стырено отсюда https://gist.github.com/kevinmoran/b45980723e53edeb8a5a43c49f134724
private static Matrix4x4 getRotateMatrix(Vector3 v1, Vector3 v2)
{
Vector3 axis = Vector3.Normalize(Vector3.Cross(v1, v2));
float dotProduct = Vector3.Dot(v1, v2);
dotProduct = Math.Max(
-1.0f,
Math.Min(1.0f, dotProduct)
);
float angleRadians = (float)Math.Acos(dotProduct);
return Matrix4x4.CreateFromAxisAngle(axis, angleRadians);
}
ну это хоть как то понятно, спасибо. Хотя оказалось, что и мой алгоритм с треугольниками работает в пространстве, за исключением двух случаев dx==0 && dz==0

и dx==0 && dy ==0 (исправил до получения картинки). Теперь уже на простом тесте работает.

Но появились новые вопросы.
- Какой еще тест(ы) можно сделать? Пока буду вершины немного передвигать на 0.01.
- Как рассчитать Епсилон? Ведь не будет работать не только с 0 но и так dx<Epsilon && dy <Epsilon
ну это хоть как то понятно
Странно. А что, #22 было не понятно?
Это как бы реализация аналитики
akidervish.
Единственно что я не стал делать это
Then one takes two arbitrary vectors Y'1 = (x'1, y'1, z'1) and Y2, such that the three vectors N, Y1, Y2 - are linearly independent
(this is almost always the case once one takes random vectors).
Then one starts Gram-Schmidt orthogonalization process taking N as the first vector. One obtains orthonormal vectos N, N1, N2.
, так как у меня уже есть ортонормальная тройка - в начале координатной системы.
Как рассчитать Епсилон? Ведь не будет работать не только с 0 но и так dx<Epsilon && dy <Epsilon
https://docs.microsoft.com/en-us/dotnet/api/system.double.... ![]()
А причем здесь вещественные числа? Меня интересует минимальный наклон прямой при котором нужно использовать другую формулу (другой вектор переноса).
По идее, Dx должно быть хотя бы >a (расстояние между парр. прямыми)
На фига?
Смотрим на картинку кубика
для связей 1-2 и подобных нужны другие вектора перемещений. Связь 2-6 тоже несколько другая, через x, y не посчитать, нужно z еще
что ты там закодировал под dx
Просто абсолютная разница координат начала и конца базовой линии.
dx=Abs(x2-x1)
для связей 1-2 и подобных нужны другие вектора перемещений. Связь 2-6 тоже несколько другая
В обоих случаях две образующие цилиндрической поверхности (см. #22) отстоят друг от друга на 180°.
1-я образующая: Matrix4x4 rotate1 = Matrix4x4.CreateRotationX(0.0f); 2-я образующая: Matrix4x4 rotate1 = Matrix4x4.CreateRotationX((float)Math.PI);
Ты издеваешься?
Во всех случаях, для любых заданных линий:
1-я образующая: Matrix4x4 rotate1 = Matrix4x4.CreateRotationX(0.0f); 2-я образующая: Matrix4x4 rotate1 = Matrix4x4.CreateRotationX((float)Math.PI);
Где здесь ветвления и условия?
float distance = ...;
List<Line> lines = new List<Line>{...};
foreach (Line l in lines) {
Line _1stGenLine = getGenLine(l, distance, 0.0f);
Line _2ndGenLine = getGenLine(l, distance, (float)Math.PI);
drawLine(l);
drawLine(_1stGenLine);
drawLine(_2ndGenLine);
}
private static Line getGenLine(Line line, float distance, float angle)
{
Vector3 pnt1 = line.Point1;
Vector3 pnt2 = line.Point2;
Vector3 ray = pnt2 - pnt1;
Matrix4x4 rotate1 = Matrix4x4.CreateRotationX(angle);
Matrix4x4 rotate2 = getRotateMatrix(Vector3.UnitX, Vector3.Normalize(ray));
Matrix4x4 rotate = Matrix4x4.Multiply(rotate1, rotate2);
Vector3 axis = Vector3.Transform(Vector3.UnitY, rotate);
Matrix4x4 translate = Matrix4x4.CreateTranslation(distance * axis);
pnt1 = Vector3.Transform(pnt1, translate);
pnt2 = Vector3.Transform(pnt2, translate);
return new Line { Point1 = pnt1, Point2 = pnt2 };
}
private static Matrix4x4 getRotateMatrix(Vector3 v1, Vector3 v2)
{
Vector3 axis = Vector3.Normalize(Vector3.Cross(v1, v2));
float dotProduct = Vector3.Dot(v1, v2);
dotProduct = Math.Max(
-1.0f,
Math.Min(1.0f, dotProduct)
);
float angleRadians = (float)Math.Acos(dotProduct);
return Matrix4x4.CreateFromAxisAngle(axis, angleRadians);
}
private class Line
{
public Vector3 Point1;
public Vector3 Point2;
}
ну нифига себе, у меня без условий и дополнительных матриц всего 3 строчки получается.
var tuple1 = Tools.RectangularTriangleSolutionAngle(dxOrig, dyOrig); double connectionAngleRadian = Tools.GradToRadian(90) - tuple1.Angle; tuple2 = Tools.RectangularTriangleSolutions(lineDistance, connectionAngleRadian);
Может на досуге проверю как работает. Что то меня сомнения берут.
ну нифига себе, у меня без условий и дополнительных матриц всего 3 строчки получается.
Я могу еще немного подсократить:
Tools.DontCareJustDoEverything();
Тоже заразились этим вирусом? ![]()
Надо тоже с вашим кодом поиграться, что бы понять почему работает. ![]()
Нет. Просто подумал, что тебе с картинками доступнее будет. ![]()


