Deutsch
Germany.ruФорумы → Архив Досок→ Программирование

Задачки любителям 3Д

1250  1 2 все
AlexNek патриот23.06.21 12:18
AlexNek
NEW 23.06.21 12:18 
в ответ akidervish 22.06.21 12:03

Для Z=0 действительно просто. Только немного не так как Вы написали.

У меня получается два подобных прямоугольных треугольника.

Один с гипотенузой "линией" и второй с гипотенузой "перемещения"

С первого находим угол, со второго две стороны: dx,dy

И затем просто перемещаем линию.

Теперь осталось Z добавить.

#21 
akidervish постоялец23.06.21 13:16
NEW 23.06.21 13:16 
в ответ AlexNek 23.06.21 12:18, Последний раз изменено 23.06.21 13:44 (akidervish)

То, что я написал, легко обобщается и на 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.

#22 
NightWatch коренной житель23.06.21 16:06
NightWatch
NEW 23.06.21 16:06 
в ответ AlexNek 22.06.21 11:50, Последний раз изменено 23.06.21 20:16 (NightWatch)
Нужен видимо еще какой то вектор указывающий направление, потому как можно целый цилиндр параллельных прямых сделать возле центральной.

Именно. Или соглашение, как расположить басис.

В примере я совмещаю ось х с направлющим вектором заданной линии.


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);
}
#23 
AlexNek патриот24.06.21 10:37
AlexNek
NEW 24.06.21 10:37 
в ответ NightWatch 23.06.21 16:06

ну это хоть как то понятно, спасибо. Хотя оказалось, что и мой алгоритм с треугольниками работает в пространстве, за исключением двух случаев dx==0 && dz==0

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

Но появились новые вопросы.

- Какой еще тест(ы) можно сделать? Пока буду вершины немного передвигать на 0.01.

- Как рассчитать Епсилон? Ведь не будет работать не только с 0 но и так dx<Epsilon && dy <Epsilon


#24 
NightWatch коренной житель24.06.21 11:15
NightWatch
24.06.21 11:15 
в ответ AlexNek 24.06.21 10:37
ну это хоть как то понятно

Странно. А что, #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.

, так как у меня уже есть ортонормальная тройка - в начале координатной системы.

#25 
NightWatch коренной житель24.06.21 11:49
NightWatch
NEW 24.06.21 11:49 
в ответ AlexNek 24.06.21 10:37
Как рассчитать Епсилон? Ведь не будет работать не только с 0 но и так dx<Epsilon && dy <Epsilon

https://docs.microsoft.com/en-us/dotnet/api/system.double.... смущ

#26 
AlexNek патриот24.06.21 12:34
AlexNek
NEW 24.06.21 12:34 
в ответ NightWatch 24.06.21 11:15
было не понятно?

Как то исходники читать привычнее смущ

#27 
AlexNek патриот24.06.21 12:39
AlexNek
NEW 24.06.21 12:39 
в ответ NightWatch 24.06.21 11:49

А причем здесь вещественные числа? Меня интересует минимальный наклон прямой при котором нужно использовать другую формулу (другой вектор переноса).

По идее, Dx должно быть хотя бы >a (расстояние между парр. прямыми)

#28 
NightWatch коренной житель24.06.21 12:58
NightWatch
NEW 24.06.21 12:58 
в ответ AlexNek 24.06.21 12:39
А причем здесь вещественные числа?

А откуда мне знать, что ты там закодировал под dx, dy, dz, Dx, а и т. д? Я вообще только ко второй странице топика понял (я надеюсь), чего же ты хочешь достичь (спасибо wasja-de).

при котором нужно использовать другую формулу

На фига?

#29 
AlexNek патриот24.06.21 13:15
AlexNek
NEW 24.06.21 13:15 
в ответ NightWatch 24.06.21 12:58
На фига?

Смотрим на картинку кубика

для связей 1-2 и подобных нужны другие вектора перемещений. Связь 2-6 тоже несколько другая, через x, y не посчитать, нужно z еще


что ты там закодировал под dx

Просто абсолютная разница координат начала и конца базовой линии.

dx=Abs(x2-x1)

#30 
NightWatch коренной житель24.06.21 13:29
NightWatch
NEW 24.06.21 13:29 
в ответ AlexNek 24.06.21 13:15
для связей 1-2 и подобных нужны другие вектора перемещений. Связь 2-6 тоже несколько другая

В обоих случаях две образующие цилиндрической поверхности (см. #22) отстоят друг от друга на 180°.

1-я образующая: Matrix4x4 rotate1 = Matrix4x4.CreateRotationX(0.0f); 
2-я образующая: Matrix4x4 rotate1 = Matrix4x4.CreateRotationX((float)Math.PI);


#31 
AlexNek патриот25.06.21 11:46
AlexNek
NEW 25.06.21 11:46 
в ответ NightWatch 24.06.21 13:29
В обоих случаях две

То бишь, как ни крути без ветвления и условий для них не обойдешься.

#32 
NightWatch коренной житель25.06.21 11:53
NightWatch
NEW 25.06.21 11:53 
в ответ AlexNek 25.06.21 11:46, Последний раз изменено 25.06.21 11:55 (NightWatch)

Ты издеваешься?

Во всех случаях, для любых заданных линий:

1-я образующая: Matrix4x4 rotate1 = Matrix4x4.CreateRotationX(0.0f); 
2-я образующая: Matrix4x4 rotate1 = Matrix4x4.CreateRotationX((float)Math.PI);

Где здесь ветвления и условия?

#33 
AlexNek патриот25.06.21 12:12
AlexNek
NEW 25.06.21 12:12 
в ответ NightWatch 25.06.21 11:53
Matrix4x4 rotate1 = и Matrix4x4 rotate1 =

Это тогда как понимать?

#34 
NightWatch коренной житель25.06.21 12:38
NightWatch
NEW 25.06.21 12:38 
в ответ AlexNek 25.06.21 12:12, Последний раз изменено 25.06.21 12:42 (NightWatch)
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;
}
#35 
AlexNek патриот25.06.21 12:53
AlexNek
NEW 25.06.21 12:53 
в ответ NightWatch 25.06.21 12:38

ну нифига себе, у меня без условий и дополнительных матриц всего 3 строчки получается.


var tuple1 = Tools.RectangularTriangleSolutionAngle(dxOrig, dyOrig);
double connectionAngleRadian = Tools.GradToRadian(90) - tuple1.Angle;
tuple2 = Tools.RectangularTriangleSolutions(lineDistance, connectionAngleRadian);


Может на досуге проверю как работает. Что то меня сомнения берут.

#36 
NightWatch коренной житель25.06.21 13:03
NightWatch
NEW 25.06.21 13:03 
в ответ AlexNek 25.06.21 12:53
ну нифига себе, у меня без условий и дополнительных матриц всего 3 строчки получается.

Я могу еще немного подсократить:

Tools.DontCareJustDoEverything();
#37 
NightWatch коренной житель25.06.21 15:36
NightWatch
NEW 25.06.21 15:36 
в ответ AlexNek 25.06.21 12:53

#38 
AlexNek патриот25.06.21 16:02
AlexNek
NEW 25.06.21 16:02 
в ответ NightWatch 25.06.21 15:36, Последний раз изменено 25.06.21 16:17 (AlexNek)

Тоже заразились этим вирусом? спок

Надо тоже с вашим кодом поиграться, что бы понять почему работает. смущ

#39 
NightWatch коренной житель25.06.21 16:08
NightWatch
NEW 25.06.21 16:08 
в ответ AlexNek 25.06.21 16:02

Нет. Просто подумал, что тебе с картинками доступнее будет. спок

#40 
1 2 все