Дмитрий
ДмитрийМаусым 28, 2020, 8:03 Т.Ж.

Qt Creator көмегімен компьютер геометриясы

Осы мақала арқылы мен диссертацияммен жұмыс істеу барысында жинақтаған компьютерлік геометрияны қолдану тәжірибеммен бөліскім келеді. Qt Creator-де геометриямен жұмыс істеуге арналған құралдар (атап айтқанда QVector3D) бар екенін бәрі біле бермейді, олар үшін орыс тілінде толық нұсқаулық жоқ. Сондықтан бұл жерде мен қажетті теория мен оның жүзеге асуын қысқаша сипаттауға тырысамын.


Нүкте және вектор

Qt ішіндегі нүктені сипаттау үшін QVector2D, QVector3D және QVector4D кластары (QVector класымен шатастырмау керек) сәйкесінше екі өлшемді, үш өлшемді және төрт өлшемді кеңістіктер үшін берілген. Іс жүзінде бұл геометриялық функциялар жиыны бар екі, үш және төрт өзгермелі айнымалылардың массивтері. Сондықтан мен барлық мысалдарды іс жүзінде ең пайдалы QVector3D үшін ғана беремін.

QVector3D v1(1,1,1) v2(1,1,1), v3(1.1f,2.5f,3.8f);

Мысалда 3 вектор берілген. Жақшада x, y, z координаталары бар. Векторлық компоненттердің кез келгенін алуға немесе қайта анықтауға болады.

v3.setX(0.5);
v3.setY(0.6);
v3.setZ(0.7);
qDebug() << v3.x() << v3.y() << v3.z() << v3;

> 0,5 0,6 0,7 QVector3D(0,5, 0,6, 0,7)

Векторларды сипаттау үшін бірдей класстар қолданылады. Сондықтан кейбір функциялардың векторлар мен нүктелер үшін әртүрлі мағыналары болады. Мысалы, нормалау дегеніміз берілген векторды бірлік ұзындықтағы векторға түрлендіру операциясы:

мұндағы - вектордың ұзындығы (модуль). Бұл үшін QVector3D екі функциясы бар:

v1.normalize(); // функция, изменяющая переменные объект
qDebug() << v1 << v2.normalized(); // функция, не переменные объект

> QVector3D(0,57735, 0,57735, 0,57735) QVector3D(0,57735, 0,57735, 0,57735)

Мысалда ұзындық түбірі үшке тең болатын вектор бірлік векторға қайта есептелді (геометриядағы мұндай нормаланған векторлар әртүрлі геометриялық операциялар үшін қажет). Мұны вектордың ұзындығын қайтаратын length() функциясымен тексеру оңай.

float L = v1.length(); // длина вектора или расстояние от точки до начала координат

Кейбір есептер бізді вектордың ұзындығы емес, оның квадраты қызықтырады. Ол үшін longSquared() функциясы берілген, ол есептеулер санын азайтады

float L2 = v1.lengthSquared();

Көптеген есептеулерді жүргізбес бұрын, пайдаланылған векторлардың нөлге тең еместігін тексеру қажет (барлық құрамдас бөліктер нөлге тең). Әйтпесе, нәтиже жеткіліксіз болады (тіпті қателер болуы мүмкін).

bool b = v1.isNull(); // проверка: является ли вектор нулевым?

Векторларды қосуға және азайтуға болады (олардың сәйкес координаттарын қосу). Сондай-ақ, векторды санға көбейтуге немесе бөлуге болады (ұзындығы бойынша n есе үлкен немесе кіші векторды алады). Көбейту операциясымен абай болу керек, өйткені. v1*v2 өрнегі векторлардың сәйкес координаталарының көбейтіндісіне келтіріледі. v1/v2 бөлу операциясы ұқсас жұмыс істейді. Алдыңғы екі операцияның геометриялық интерпретациясы координаттар жүйесін v2-де көрсетілген мәндер бойынша сәйкес осьтер бойымен созу және кішірейту болып табылады. dotProduct(v1, v2) және crossProduct(v1, v2) функциялары нүктелік және векторлық өнімдерді жүзеге асыру үшін қамтамасыз етілген.

QVector3D v11(1,0,0), v12(0,1,0);
qDebug() << v11*v12 <<  QVector3D::dotProduct(v11, v12) <<  QVector3D::crossProduct(v11, v12);

> QVector3D(0, 0, 0) 0 QVector3D(0, 0, 1)

Естеріңізге сала кетейін, екі вектордың скаляр көбейтіндісі ретінде анықталған сан

ал нормаль векторларды көбейту кезінде олардың арасындағы бұрыштың косинусына тең болады.
Айқас көбейтіндіні келесідей есептеуге болады

мұндағы i, j, k – декарттық координаталар жүйесінің ортылары, тура жақшалар (мұнда және төменде) матрицаның анықтаушысы болып табылады. Бұл операцияның нәтижесі екі факторлық вектор жатқан жазықтыққа перпендикуляр вектор немесе v1 және v2 коллинеар болса нөлдік вектор болып табылады. Векторлық көбейтіндінің модулі факторлардың модульдерінің көбейтіндісіне және олардың арасындағы бұрыштың синусына тең.
Векторлардың теңдігін тексеруге болады. Барлық сәйкес координаталар тең болғанда екі вектор тең болады. Дегенмен, күрделі есептеулер кезінде қате жиналуы мүмкін екенін есте ұстаған жөн. Сондықтан әзірлеушілер «жұмсақ» салыстыру мүмкіндігін берді.

v2 = v1 + QVector3D(0.000001f, 0.000001f, 0.000001f);
qDebug() << (v1 == v2) << qFuzzyCompare(v1, v2);

> жалған ақиқат

Екі нүктенің арақашықтығы арқылы берілген

remoteToPoint(v2) функциясына ендірілген

QVector3D v1(0,1,1), v2(1,0,1);
qDebug() << v1.distanceToPoint(v2);

> 1,41421

Векторлар үшін соңғы операцияның мәні олардың айырмасының векторының ұзындығы болып табылады.

qDebug() << (v1-v2).length();

> 1,41421

Ұшақ

Кез келген жазықтықты бір түзуде жатпайтын үш жұп сәйкес келмейтін T1, T2 және T3 нүктелері арқылы анықтауға болады. Тағы бір ыңғайлы сипаттама жазық теңдеуді пайдалану болып табылады:

мұндағы A, B, C және D – T1, T2 және T3 нүктелерінің координаталары арқылы есептелетін коэффициенттер,

(A, B, C) - жазықтыққа нормаль векторы, D - бос коэффициент. Алынған нәтижені қалыпқа келтіруге болады

(a, b, c) жазықтыққа дейінгі бірлік нормаль векторы, d - жазықтықтан координаталар басына дейінгі қашықтық (егер нормаль вектор координаталар координаттары бар жартылай жазықтыққа бағытталған болса, «плюс» белгісімен, әйтпесе – «минуспен»).
Жазықтықтың нормаль векторын аргументтері үш нүкте (жоғарыда көрсетілгендей) немесе екі коллинеар емес вектор болуы мүмкін normal(…) статикалық функциясы арқылы есептеуге болады. Екі векторды T1 – T2, T2 – T3, ал нормальды олардың векторлық сызығы ретінде беруге болатыны анық.

QVector3D v1(0,0,1), v2(0,1,0), v3(1,0,0); // корректно заданная плоскость
qDebug() << QVector3D::normal(v1, v2, v3), QVector3D::normal(v1 - v2, v2 - v3), QVector3D::crossProduct(v1 - v2, v2 - v3).normalized();

> QVector3D(-0,57735, -0,57735, -0,57735) QVector3D(-0,57735, -0,57735, -0,57735) QVector3D(-0,57735, -0,577735, -35).

Егер жоғарыда сипатталған кіріс деректеріне қойылатын талаптар орындалмаса, нәтиже нөлдік вектор болады

QVector3D v01(0,0,10), v02(0,0,20), v03(0,0,30); // некорректно заданная плоскость
qDebug() << QVector3D::normal(v01, v02, v03) << QVector3D::normal(v01 - v02, v02 - v03);

> QVector3D(0, 0, 0) QVector3D(0, 0, 0)

Ұшақтың жоғарыдағы сипаттамасы ең жинақы (4 сан). Бірақ ең қолайлысы - жазықтықты бір нүкте (T0) және қалыпты вектор (6 сан) арқылы сипаттау. Бұл көрініс келесі әрекеттерді ұйымдастыруды жеңілдетеді.

Тиісті ұшақ

Егер Т нүктесі жазықтықта жатса, оның координаталарын жазықтықтың теңдеуіне қойып, 0 аламыз. Нүкте және вектор арқылы көрсетуде

Басқаша айтқанда, T – T0 векторы n нормаль векторына перпендикуляр.

Бір жарты кеңістікте

Ұшақ кеңістікті екі жарты кеңістікке бөледі. Алдыңғы өрнек егер T нүктесі олардың біреуінде болса, оң мәндерді, ал екіншісінде болса теріс мәндерді қабылдайды. Демек, 2 нүкте T1 және T2 бірдей жарты кеңістікте жатыр, егер

Т нүктесінің жазықтыққа проекциясы

Нүктеден жазықтыққа дейінгі қашықтық

нүктеден оның жазықтыққа проекциясына дейінгі қашықтық

Ол аргументтері жазықтық параметрлері (нүкте және вектор немесе үш нүкте) болып табылатын remoteToPlane(...) функциясы арқылы анықталады.

QVector3D T(2,2,2);// точка
QVector3D n(-1,-1,-1), T0(1,1,1);// плоскость
qDebug() << T.distanceToPlane(T0,n) << QVector3D::dotProduct(T-T0, n);// неправильный расчёт: нормальный вектор не нормализован
qDebug() << T.distanceToPlane(T0,n.normalized()) << QVector3D::dotProduct(T-T0, n)/n.length();//правильный расчёт

>-3 -3
-1,73205 -1,73205

Алынған мәнге T жарты жазықтықта жататынына сәйкес қол қойылғанын ескеріңіз.

Т нүктесінің жазықтықтан айнамен шағылуы

Түзу

Кеңістіктегі түзу екі (сәйкес келмейтін) T1 және T2 нүктелері арқылы толығымен сипатталады. Qt тілінде T1 нүктесі және K = T2 – T1 бағыт векторы бар түзуді сипаттау әдеттегідей.

немесе

мұндағы (ΔX, ΔY, ΔZ) = K. Бұл векторды нормалау да мақсатқа сай.

Т нүктесінің түзу сызыққа жатуы

(T – T1) және k векторларының коллинеарлылығын (айқас көбейтінді – нөл векторы) тексеру қажет.

Т нүктесінің түзу проекциясы

Нүктенің жазықтыққа проекциясы есебінің шешімдерін талдау арқылы келесі өрнекті оңай алуға болады.

Т нүктесінен түзу сызыққа дейінгі қашықтық

Жоғарыда айтылғандарға сәйкес

Нүктеден түзуге дейінгі қашықтық қашықтықToLine(...) функциясы арқылы анықталады, оның аргументтері нүкте және түзудің бағыт векторы болып табылады.

QVector3D T(2,2,2);// точка
QVector3D k(1,1,0), T1(0,0,1);// плоскость
QVector3D R = T - T1 - k*QVector3D::dotProduct(k, T - T1);
qDebug() << T.distanceToLine(T1,k) << R.length(); // неправильный расчёт: направляющий вектор не нормализован
R = T - T1 - k*QVector3D::dotProduct(k, T - T1)/k.lengthSquared();
qDebug() << T.distanceToLine(T1,k.normalized()) << R.length(); // правильный расчёт

>3 3
1 1

Түзу мен жазықтықтың қиылысуы

Түзу (k, T1) жазықтыққа параллель болуы мүмкін (n, T0). Бұл жағдайда анықтаушы векторлар перпендикуляр болады, бұл олардың скаляр көбейтіндісінің теңдігін тексеру арқылы тексеріледі. Әйтпесе, түзу мен жазықтықтың қиылысу нүктесі ретінде анықталған

Жоғарыда келтірілген формулада алдыңғылардан айырмашылығы нормаланған векторларды пайдалану қажет емес. Егер қиылыс болмаса, T1 нүктесінің жазықтыққа жататынын тексеріп, түзудің онда жатқанын анықтауға болады.

Қорытынды

Мақаланы соңына дейін оқығандардың барлығына рахмет. Болашақта осы тақырыпты дамытуды жоспарлап отырмын. Сондықтан, тақырып бойынша сұрақтарыңыз болса, оларды түсініктемелерде жазыңыз.

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

Ол саған ұнайды ма? Әлеуметтік желілерде бөлісіңіз!

Evgenii Legotckoi
  • Маусым 29, 2020, 4:05 Т.Ж.

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

Вообще прлюс использования скалярной математики при расчётах углов отражений в том, что это менее затратный операции, чем использование тригонометрии (синусы/косинусы и т.д.)

Дмитрий
  • Шілде 1, 2020, 5:56 Т.Ж.

Скалярная математика и тригонометрия - суть одно и тоже. Просто разные языки описания одного предмета. В конечном итоге для расчёта коэффициента отражения нужно знать косинус угла падения.

Подскажите, какой инструмент лучше использовать для визуализации 3D объектов.

Evgenii Legotckoi
  • Шілде 1, 2020, 6:09 Т.Ж.
  • (өңделген)

Вы очень сильно заблуждаетесь.

Вот формула для расчёта отражённого вектора. Расчёт углов через косинусы и синусы не требуется от слова совсем .

Подробнее обсуждение в этом топике

При написании арканоида для медицинского оборудования я пользовался именно математикой скалярных векторов. Поэтому и утверждаю, что использование скалярной математики в разы разгружает процессорные мощности. Это основы написания игровых движков.

Визуализацию можно и в Qt делать. Насколько помню по новостям там есть поддержка импорта 3D объектов даже. Также есть примеры визуализации некоторых вещей в самом Qt Creator.

На нашем проекте используется OpenCascade - достаточно мощная вещь. Главное написать код для QWidget, чтобы отображать результат. Но сам я в той части кода не работаю. Не моя область проекта.

Дмитрий
  • Шілде 2, 2020, 6:16 Т.Ж.

Не согласен. Произведение l на n - это косинус угла между ними умноженный на их длины. Если бы оба вектора были единичными, то остался бы "чистый" косинус. Просто при используемом описании тригонометрия скрыта от нас.

Дмитрий
  • Шілде 2, 2020, 6:19 Т.Ж.

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

Evgenii Legotckoi
  • Шілде 2, 2020, 6:50 Т.Ж.

Да, согласен. Освежил в памяти. Вот определение из лекций

Скалярным произведением ненулевых векторов a и b называется число, равное произведению длин этих
векторов на косинус угла между ними. Если среди векторов a и b
есть хотя бы один нулевой, то скалярное произведение равно нулю.

Тем не менее, косинус здесь знать не нужно, вот к чему я это говорил

В конечном итоге для расчёта коэффициента отражения нужно знать косинус угла падения.

Естественно, что скалярное произведение векторов отражает явления тригономитреческих функций и может быть сопоставлено. Иначе это было бы странно. Насколько помню - это выводится через последовательное доказательство леммами, но не через прямые расчёты и формулы. Поэтому утверждение имеет доказательную базу, а знать косинус не нужно ;-)

Пікірлер

Тек рұқсаты бар пайдаланушылар ғана пікір қалдыра алады.
Кіріңіз немесе Тіркеліңіз
Г

C++ - Тест 001. Первая программа и типы данных

  • Нәтиже:66ұпай,
  • Бағалау ұпайлары-1
t

C++ - Тест 001. Первая программа и типы данных

  • Нәтиже:33ұпай,
  • Бағалау ұпайлары-10
t

Qt - Тест 001. Сигналы и слоты

  • Нәтиже:52ұпай,
  • Бағалау ұпайлары-4
Соңғы пікірлер
G
GoattRockҚыр. 3, 2024, 1:50 Т.Қ.
Linux жүйесінде файлдарды қалай көшіруге болады Задумывались когда-нибудь о том, как мы привыкли доверять свои вещи службам грузоперевозок? Сейчас такие услуги стали неотъемлемой частью нашей жизни, особенно когда речь идет о переездах между …
d
dblas5Шілде 5, 2024, 11:02 Т.Ж.
QML - Сабақ 016. SQLite деректер қоры және онымен QML Qt-та жұмыс істеу Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
k
kmssrАқп. 8, 2024, 6:43 Т.Қ.
Qt Linux - Сабақ 001. Linux астында Autorun Qt қолданбасы как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
АК
Анатолий КононенкоАқп. 5, 2024, 1:50 Т.Ж.
Qt WinAPI - Сабақ 007. Qt ішінде ICMP Ping арқылы жұмыс істеу Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
Енді форумда талқылаңыз
Evgenii Legotckoi
Evgenii LegotckoiМаусым 24, 2024, 3:11 Т.Қ.
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
F
FynjyШілде 22, 2024, 4:15 Т.Ж.
при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …
BlinCT
BlinCTМаусым 25, 2024, 1 Т.Ж.
Нарисовать кривую в qml Всем привет. Имеется Лист листов с тосками, точки получаны интерполяцией Лагранжа. Вопрос, как этими точками нарисовать кривую? ChartView отпадает сразу, в qt6.7 появился новый элемент…
BlinCT
BlinCTМамыр 5, 2024, 5:46 Т.Ж.
Написать свой GraphsView Всем привет. В Qt есть давольно старый обьект дял работы с графиками ChartsView и есть в 6.7 новый но очень сырой и со слабым функционалом GraphsView. По этой причине я хочу написать х…
Evgenii Legotckoi
Evgenii LegotckoiМамыр 2, 2024, 2:07 Т.Қ.
Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Добрый день. По моему мнению - да, но то, что будет касаться вызовов к функционалу Андроида, может создать огромные трудности.

Бізді әлеуметтік желілерде бақылаңыз