Задачки любителям 3Д
Вот в первый раз столкнулся, пока не придумал решение. Нужно чисто для личных целей.
1. Есть прямая заданная двумя точками (x,y,z). Нужно нарисовать еще одну параллельную прямую н расстоянии а в плоскости xy.
2. Есть лого которое надо наложить на сферу так что бы оно было видно с любой стороны. Тут видимо надо делить по 120 градусов на три оси и в эти треугольники вписывать. Только вот как текстуру такую сгенерить?
3. С материалом для мешей еще не разобрался до конца. Есть там Diffuse Color и Emissive Color. Основной цвет я присваиваю в Emissive Color, а второй подбираю. А формула есть для второго цвета?
1. Есть прямая заданная двумя точками A(x1,y1,z1), B(x2,y2,z2). Нужно нарисовать еще одну параллельную прямую на расстоянии а в плоскости xy.
Если перпендикуляры от A и B на плоскость не равны друг другу, то параллельную прямую с одинаковым расстоянием до прямой, проходящей через A и B провести нельзя. Может Вы как-то по-другому плоскость хотели задать?
2. Есть лого которое надо наложить на сферу так что бы оно было видно с любой стороны. Тут видимо надо делить по 120 градусов на три оси и в эти треугольники вписывать. Только вот как текстуру такую сгенерить?
Не, криво как-то. Может можно узнать вектор откуда смотрят, и двигать центр лого на нужное место?
1. Есть прямая заданная двумя точками (x,y,z). Нужно нарисовать еще одну параллельную прямую н расстоянии а в плоскости xy.
Мнэ... По геометрии что в школе было? Что за "плоскость xy"?
2. Есть лого которое надо наложить на сферу так что бы оно было видно с любой стороны.
С любой стороны чего? Было видно что? Решение - минимизирую лого до одного пикселя и заливаю всю поверхность сферы этим пикселем. Видно отовсюду. Задача решена.
Уравнение прямой
k1X + k2Y + k3Z = 0
Это не уравнение прямой, а уравнение плоскости.
Но задача 1) сформулирована не ясно. Там, видимо, опечатка в условии, т.к. даже с точки зрения русской грамматики не ясно, что хотели спросить:
еще одну параллельную прямую н расстоянии а в плоскости xy.
Вторая прямая должна целиком лежать в плоскости ортогональной Оz и проходящей через (0,0,0)? Если изначальная прямая не параллельна этой плоскости,
то, как написал вася, это сделать невозможно.
Упссс... а ведь подзабыл... действительно - плоскость... и для определения прямой задавать их надо две штуки...
Ну либо к канонической форме переходить = (х-х0)/к1 = (y-y0)/k2=(z-z0)/k3...
Блин, давнен'ко не пользовался аналитической геометрией...
Прямую можно задать параметрически, через параметр t в векторном виде.
Если \vec{X} = (X,Y,Z),
then: \vec{X}(t) = (\vec{X}_1 - \vec{X}_2) * t + \vec{X}_2 - equation defining the line passing through the points \vec{X_1}, \vec{X}_2
(ends of the vectors for different t \in (-\inf, +\inf) define this line).
You can shift with a vector \Delta \vec{X}_0 in any direction:
\vec{X}'(t) = (\vec{X}_1 - \vec{X}_2) * t + \vec{X}_2 +\Delta \vec{X}_0, such that |\Delta \vec{X}_0| = \sqrt{x_0^2 + y_0^2 + z_0^2} = a.
NOTE: such a shift of the plane:
k1(X+a) + k2(Y+a) + k3(Z+a) = 0
results in the shift by the vector of length = a * \sqrt(k1^2 + k2^2 + k3^2) != a (the distance between planes will not be, in general, equal to a).
Может Вы как-то по-другому плоскость хотели задать?
А вообще непонятно как, совершенно неправильно было. Нужен видимо еще какой то вектор указывающий направление, потому как можно целый цилиндр параллельных прямых сделать возле центральной.
Не, криво как-то.
Почему? Во всех примерах накладывают текстуру на объект. Да и следить за вращением не хочется. Можно ведь не только сцену вращать но и конкретный объект.
По геометрии что в школе было?
Спросили бы еще, что в детском саду на обед давали Ни разу еще ничего подобного не нужно было.
Вот что имелось в виду
минимизирую лого до одного пикселя
И как различать различные лого, если они только по форме отличаются?
Ваша изначальная кривая в середине?
И все три лежат в плоскости z = 0?
Тогда просто:
прямая проходит через точки Х1 = (х1,y1, 0) and X2 = (x2, y2, 0).
X(t) = (X1 - X2) t + X2.
N = (X1 - X2) / |X1 - X2|
|X| = sqrt(x^2 + y^2 + z^2)
denote coordinates of N = (n1, n2, 0), n1^2 + n^2 = 1
N' = (-n2, n1, 0)
X' (t) = (X1 - X2) t + X2 + a * N'/2
X"(t) = (X1 - X2) t + X2 - a * N'/2
in vector form:
параметрические уравнения ваших прямых (сдвинуты от центральной на +/-а/2 в
ортогональном к серединной прямой направлении внутри z=0 плоскости).
Если вы прямые задаете двумя точками, просто возьмите два разных t, e.g. t=0, 1.
сформулирована не ясно.
совершенно верно
Проблема заключается в том, что я не знаю как именно нарисовать эту прямую. Варинтов то дофига.
Возможно можно сказать так: в начальном положении камеры должно быть видно максимальное количество прямых.
Если исключить прямые лежащие на оси Z, то все дополнительные прямые должны проецироваться на плоскость проходящую через оси X,Y (Как эту плоскость назвать?)
Ваша изначальная кривая в середине?
Можно считать и так. Мне известны именно эти две точки. Нарисовать нужно или одну или две(без центральной) или три прямых. Для этого есть дополнительные условия.
И все три лежат в плоскости z = 0?
Нет, просто так удобнее было отрисовать. Располагаться прямые могут как угодно.
Тогда просто:
Спасибо, вечером гляну.
или мы о проекциях на плоскость z=0 говорим...
Скорее это. Просто для картинки было наглядней не вносить 3ю координату.
Камера смотрит по умолчанию примерно так, как показано. Поэтому желательно, что бы было видно как можно больше линий, вероятно линии нужно располагать вдоль вектора совпадающего с осью Y.
А то меня тут 3Д заразили, сижу с линиями уже мучаюсь. Пока только одну линию осилил.
А то меня тут 3Д заразили, сижу с линиями уже мучаюсь. Пока только одну линию осилил. C6H8O6
Вам кроме основ геометрии хорощо было бы еще химию подучить. В химии при нарисовке двойной связи принято учитывать расположение Пи-орбиталей - они должны быть над и под плоскостью, где лежит плоскость, в которой находятся оба отрезка, символизирующие двойную связь.
В принципе там ничего страшного, и погуглив и внимательно поизучав то, что есть на ключевые слова Уравнение Шредингера, приближение Борна Опенгеймера, методы Хартри-Фока, s, p, d, f орбитали. Но вот как Вы без знания алгоритмов хотя бы молекулярной механики сможете эту информацию получать, ума не приложу. Кстати, в Пабчеме сплош и рядом ошибки в такой визуализации.
сможете эту информацию получать
А у меня и не стоит задача ее получать
Достаточно того, что могу стибрить из SDF Pubchema
Я не собираюсь делать софт для химиков, мне интересно изучить что-то новое в программировании. В данном случае - это Blazor для веба с НЕТ 5.0.
Я поставил себе задачу нарисовать в 3Д относительно произвольную молекулу. Разноцветные шарики разного диаметра с одиночными связями уже получаются без проблем по стандартному описанию.
Правда в SDF не нашел информацию о размере и цвете атомов. Ну и не все поля еще раскодировал.
Теперь вот следующий шаг - сделать 2х и 3х связи.
хорошо было бы еще химию подучить
В принципе можно, но не вижу куда это в дальнейшем это можно применить. Да и всё изучить всё равно невозможно.
в Пабчеме сплош и рядом ошибки в такой визуализации.
Больше я пока не знаю на что можно ориентироваться. Как откроете официально ваш сайт смогу на него равняться.
принято учитывать расположение Пи-орбиталей
Если данная информация отсутствует в описании, то для меня она как то и не существует. Это как ТЗ, чего нет в ТЗ, то не делаем
Если данная информация отсутствует в описании, то для меня она как то и не существует. Это как ТЗ, чего нет в ТЗ, то не делаем
не, почему-же, я довольно понятно рассказал в моем предыдущем ответе как из SDF или MOL можно получить информацию в какой плоскости должны лежать отрезки у двойной связи, только Вы не прислушались, или не захотели почему-то. Пабчем эту информацию иногда с ошибкой считает, мне не понятно почему. Мне играться в 3Д через WebGL пока нужды нет, так как квантовомеханические расчеты у меня еще не закончены, пока есть только результаты молекулярной механики, а их можно и псевдо3Д без теней нарисовать как у меня сделано.
понятно рассказал в моем предыдущем ответе как из SDF или MOL можно получить информацию
Очень понятно - Уравнение Шредингера, приближение Борна Опенгеймера...
при том что SDF вообще не упоминалось
Это как бы если кто то хотел сделать калькулятор, а ему - изучи циклы, ветвления и немного программирования, делать там нефиг.
Да и даже если я это изучу, проблема то всё равно останется, параллельные прямые к химии вроде отношения не имеют.
У нас подход разный к задачам.
Я вот не буду разработчику автокада рекомендовать изучить моторы и их принцип действия.
Для 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....
На фига?
Смотрим на картинку кубика
для связей 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);
Может на досуге проверю как работает. Что то меня сомнения берут.