Название: От С++ к Qt C++ Отправлено: Skrypnyk от Март 17, 2013, 11:19 Здравствуйте!
Я делаю проект для учебы. Мне нужно создать массив атомов. В этом массиве юзер выбирает плоскость используя индексы Миллера. На экране должны быть отображены атомы, принадлежащие плоскости. Я написал код в С++: Код: /* I. Create a FCC lattice Я смотрел видео на Ютюбе, читал документацию Qt, но ничего конкретного для решения моей проблемы не нашел. Основной дилеммой является визуализация атомов в плоскости (Аtom11 - Atom44). Подскажите, пожалуйста, какие-нибудь источники или посоветуйте что-нибудь для решения моей проблемы. Заранее благодарен! Название: Re: От С++ к Qt C++ Отправлено: Igors от Март 17, 2013, 12:45 Приведенный код называется "не ленивый программист" (ужасно). Ладно, об этом Вы не спрашивали, чисто по алгоритму:
Зачем Вы связались с поворотами? Что Вы от них хотели? Вам надо найти точки принадлежащие данной плоскости - ну и находите. Задайте плоскость вектором (a, b, c) + расстоянием до начала координат (d) и спокойно находите расстояние до нее Код Вот и вся любовь Название: Re: От С++ к Qt C++ Отправлено: Dancing_on_water от Март 17, 2013, 12:51 Э-кхм, начну с того, что неплохо подучить C++ как таковой.
В вашем коде стек уже забит дай боже как, еще что-либо в подобном роде и программа начнет вылетать с криками: "Stack Overflow". Теперь к самому вопросу: Если вам нужен 3d с кучей объектов, то тут openGL без вариантов. Если 2d , то пойдет QGraphicsScene Все прочее не подходит, т.к. у вас в одной плоскости уже 1000 объектов. Название: Re: От С++ к Qt C++ Отправлено: Skrypnyk от Март 17, 2013, 13:46 Приведенный код называется "не ленивый программист" (ужасно). Ладно, об этом Вы не спрашивали, чисто по алгоритму: Зачем Вы связались с поворотами? Что Вы от них хотели? Вам надо найти точки принадлежащие данной плоскости - ну и находите. Задайте плоскость вектором (a, b, c) + расстоянием до начала координат (d) и спокойно находите расстояние до нее Код Вот и вся любовь Повороты нужны для отображения плоскости проекции. Таким образом мы будем смотреть по направлению нормали к плоскости и получим реальные расстояния между атомами на экране. Название: Re: От С++ к Qt C++ Отправлено: Skrypnyk от Март 17, 2013, 13:50 Э-кхм, начну с того, что неплохо подучить C++ как таковой. В вашем коде стек уже забит дай боже как, еще что-либо в подобном роде и программа начнет вылетать с криками: "Stack Overflow". Теперь к самому вопросу: Если вам нужен 3d с кучей объектов, то тут openGL без вариантов. Если 2d , то пойдет QGraphicsScene Все прочее не подходит, т.к. у вас в одной плоскости уже 1000 объектов. Я недавно учу С++, причем программирование - не основное направление моей учебы. Но мне интересно. Жаль, что времени мало. Спасибо за ответ. Буду читать о QGraphicsScene. Название: Re: От С++ к Qt C++ Отправлено: Igors от Март 17, 2013, 14:31 Лучше не злоупотреблять цитированием если и так ясно о чем речь
Повороты нужны для отображения плоскости проекции. Таким образом мы будем смотреть по направлению нормали к плоскости и получим реальные расстояния между атомами на экране. Экран всего лишь отображает, поэтому расстояния на экране реальными быть не могут :) Если же Вы хотите отобразить на экране секущую плоскость (с найденными точками), то Вам совершенно не нужно изучать какие-то мудреные классы и/или OpenGL. Надо просто перевести найденные точки в экранные координаты построив матрицу поворота. Сначала выведите исходные точки в плоскости XYКод Чтобы нарисовать найденные точки - все то же самое, только сначала надо помножить точку на матрицу. Чтобы воздух не гонять - нарисуйте исходные, а матрицу я Вам покажу Название: Re: От С++ к Qt C++ Отправлено: Skrypnyk от Март 17, 2013, 21:08 Igors, я получил двухмерные координаты точек секущей. Теперь хотелось бы их визуализировать. Как это сделать, если всем точкам отвечают элементы массива с координатами x, y (Atom11 [j][k].x, Atom11 [j][k].y, и то же для атомов типа 22, 33, 44)?
В Вашей функции Atom2Screen первый аргумент Цитировать const Atom & atom требует ввода указателя, если я не ошибаюсь. Мне нужно создать указатель?Название: Re: От С++ к Qt C++ Отправлено: Igors от Март 18, 2013, 12:17 В Вашей функции Atom2Screen первый аргумент Это "ссылка", в данном случае константная. Просто подавайте в ф-цию элемент массива, указатель создавать не нужно. Подробнее о ссылках - см любую книгу по С++ Цитировать const Atom & atom требует ввода указателя, если я не ошибаюсь. Мне нужно создать указатель?я получил двухмерные координаты точек секущей. Теперь хотелось бы их визуализировать. Как это сделать, если всем точкам отвечают элементы массива с координатами x, y (Atom11 [j][k].x, Atom11 [j][k].y, и то же для атомов типа 22, 33, 44)? Визуализация (перевод в экранные координаты) в любом случае выполняется ф-цией которую я привел в предыдущем посте. Если 2 или более точек совпадают в данной проекции - ну увидите их все вместе как одну, это нормально.То что Вы реализовали называется "углы Эйлера" (последовательность поворотов). Это длинно и мутно, "зато" в данном случае совершенно неуместно и неправильно. Нужно получить уравнения секущих плоскостей из отрезков Миллера. Это можно сделать напр так Код Если a, b, c нули или единицы - одна плоскость, иначе "семейство". Название: Re: От С++ к Qt C++ Отправлено: Skrypnyk от Март 18, 2013, 15:12 Igors, спасибо за Ваш ответ. Очень ценная для меня информация. Я использовал углы Эйлера, потому что это был единственный доступный для меня инструмент поворота. У меня есть несколько вопросов по части приведенного Вами кода:
1. QVector <QVector4D> & plane - что нужно вводить как аргумент при вызове функции Miller2Plane (1,1,1, ?)? И зачем нужен QVector4D? Чему отвечает 4-я координата? 2. push_back() - эквивалентно append (), как я понял из документации Кьют. Т.е. добавляет в конец вектора новое значение? 3. assert(vec.size() > 0) - зачем оценивать количество элементов вектора именно на этом этапе (оценки равны или нет переменные a, b, c нулю)? 4. back()? - зачем возвращать ссылку на последний вектор? 5. В Вашей записи vec
Код: plane.push_back(QVector4D(nor, -QVector3D::dotProduct(nor, vec[0]))); Зачем нужно скалярное произведение нормали к плоскости с, как я понимаю, первым отрезком Миллера? Да еще и со знаком минус? Название: Re: От С++ к Qt C++ Отправлено: Igors от Март 18, 2013, 18:32 Простейший случай: индекс = (1, 1, 1). Одна секущая плоскость по диагонали. cntr + axisX(Y, Z) есть 3 точки лежащие в этой плоскости. Уравнение плоскости
ax + by + cz + d = 0; a, b, c - нормаль к плоскости, d - расстояние до начала координат. Если подставить точку (x. y. z) в это уравнение, результат будет (знаковое) расстояние от точки до плоскости. Если точка лежит на плоскости, то уравнение даст ноль. Находим нормаль и d и записываем это в Vector4D Если все 3 индекса == 0, это случай недопустимый, вываливаемся по assert. А вот 1 или 2 индекса могут быть нулевыми - ось(и) параллельны плоскости. Тогда cntr+axis не проходит, но мы можем добавить отрезок оси к уже имеющейся на плоскости точки - и получить новую. Да, все это "аналитическая геометрия", курс первого семестра который традиционно считается легким (в теории). По поводу остальных Ваших вопросов по векторам и др - общий ответ "да" и учите плюсы, по-другому не получится Название: Re: От С++ к Qt C++ Отправлено: Skrypnyk от Март 18, 2013, 18:42 Получается вместо QVector <QVector4D> & plane при вызове функции Miller2Plane должно быть записано расстояние от начала координат до плоскости?
Название: Re: От С++ к Qt C++ Отправлено: Igors от Март 18, 2013, 18:57 Получается вместо QVector <QVector4D> & plane при вызове функции Miller2Plane должно быть записано расстояние от начала координат до плоскости? Что-то совсем мрачно :'( Как Вы знаете, 3 индекса Миллера могут задавать любое число секущих плоскостей, поэтому ф-ция заполняет контейнер (вектор) каждый элемент которого QVector4D описывающий секущую плоскость: x, y, z есть нормаль к плоскости и w - расстояниеНазвание: Re: От С++ к Qt C++ Отправлено: m_ax от Март 18, 2013, 20:07 Получается вместо QVector <QVector4D> & plane при вызове функции Miller2Plane должно быть записано расстояние от начала координат до плоскости? Что-то совсем мрачно :'( Как Вы знаете, 3 индекса Миллера могут задавать любое число секущих плоскостей, поэтому ф-ция заполняет контейнер (вектор) каждый элемент которого QVector4D описывающий секущую плоскость: x, y, z есть нормаль к плоскости и w - расстояниеА если вектора кристаллической решётки не ортогональны? ;) Название: Re: От С++ к Qt C++ Отправлено: Igors от Март 18, 2013, 21:07 А если вектора кристаллической решётки не ортогональны? ;) На здоровье - задавайте неортогональные axisX(Y, Z) Название: Re: От С++ к Qt C++ Отправлено: Skrypnyk от Март 18, 2013, 23:22 Igors, тогда еще вопрос: -QVector3D::dotProduct(nor, vec[0]) - тоже получается расстояние в функции QVector4D(nor, -QVector3D::dotProduct(nor, vec[0]))?
И еще хочу поинтересоваться: в чем смысл трех вложенных циклов for? Я задаю столько вопросов, потому что не силен в программировании, а мне нужно знать какие процессы описываются приведенным Вами кодом. Я не сомневаюсь, что он дает результат. Но хочется узнать что он делает, чтобы получить конечный результат. Еще раз спасибо. Название: Re: От С++ к Qt C++ Отправлено: Igors от Март 19, 2013, 11:53 -QVector3D::dotProduct(nor, vec[0]) - тоже получается расстояние в функции QVector4D(nor, -QVector3D::dotProduct(nor, vec[0]))? Уравнение плоскости ax + by + cz + d = 0;Отсюда d = -(ax + by + cz); В правой части скалярное произведение нормали к плоскости (a, b, c) на точку лежащую на ней (x, y, z) И еще хочу поинтересоваться: в чем смысл трех вложенных циклов for? В том что (судя по картинкам в Вике) отрезки Миллера могут задавать множество (семейство) секущих плоскостей, напр (1, 1, 2) уже 2 плоскостиНазвание: Re: От С++ к Qt C++ Отправлено: Skrypnyk от Март 19, 2013, 21:14 Ага, спасибо, Ваша правда)).
А по поводу индексов Миллера, то это величины, обратные к отрезкам, отсекаемым плоскостью на координатных осях. Например, если мы запишем плоскость (2, 2, 2) используя индексы Миллера в круглых скобках, то мы обозначим единственную плоскость, которая пересекает оси в точках (1/2; 0; 0), (0; 1/2; 0) и (0; 0; 1/2). Если же записать {2, 2, 2} в фигурных скобках, тогда речь идет о семействе плоскостей (они являются семейством в силу симметрии): (-2, -2, -2), (-2, 2, -2), (-2, -2, 2)... (2, 2, 2). Поэтому 3 вложенных цикла, я полагаю, можно убрать. Да, еще хотелось бы заметить, что нормаль к плоскости (2, 2, 2) - это вектор [2, 2, 2]. В последнем случае 3 числа в квадратных скобках обозначают вектор с началом в точке (0; 0; 0) и концом в точке (2; 2; 2). Название: Re: От С++ к Qt C++ Отправлено: Igors от Март 20, 2013, 12:45 А по поводу индексов Миллера, то это величины, обратные к отрезкам, отсекаемым плоскостью на координатных осях. Например, если мы запишем плоскость (2, 2, 2) используя индексы Миллера в круглых скобках, то мы обозначим единственную плоскость, которая пересекает оси в точках (1/2; 0; 0), (0; 1/2; 0) и (0; 0; 1/2). Если же записать {2, 2, 2} в фигурных скобках, тогда речь идет о семействе плоскостей (они являются семейством в силу симметрии): (-2, -2, -2), (-2, 2, -2), (-2, -2, 2)... (2, 2, 2). А я чего-то, бегло глянув Вику, подумал не так - ну Вам виднее :)Да, еще хотелось бы заметить, что нормаль к плоскости (2, 2, 2) - это вектор [2, 2, 2]. В последнем случае 3 числа в квадратных скобках обозначают вектор с началом в точке (0; 0; 0) и концом в точке (2; 2; 2). Тогда еще проще получается - сразу готовая нормаль и точка (напр cntr + (1/2, 0, 0)). Займитесь визуализацией исходных точек и тех что лежат на секущих плоскостях. Считайте все в реальных/исходных координатах (в тех что задавали точки) и получайте в пикселях только перед выводом. A когда дело дойдет до разворота плоскости - я Вам матрицу нарисую.Edit: нормаль готова "прямо из отрезков" только если оси ортогональны, иначе придется все равно находить 3 точки как выше |