| Правила | Регистрация | Пользователи | Сообщения за день |  Справка по форуму | Файлообменник |

Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > Тригонометрические функции и векторная алгебра

Тригонометрические функции и векторная алгебра

Ответ
Поиск в этой теме
Непрочитано 20.11.2009, 18:38
Тригонометрические функции и векторная алгебра
Supermax
 
Руководитель фирмы
 
Москва
Регистрация: 28.03.2007
Сообщений: 1,831

Решил переделать тему и собрать тут все, необходимое для вычислений в пространстве модели Автокада.

Вычисление расстояния от точки до точки:
(distance <точка1> <точка2>)
Аргуметы в виде списков (X Y Z)
В книге Н. Н. Полещука "AutoLISP и Visual Lisp в среде AutoCAD" в этой функции опечатка.
Цитата:
... Если точки трехмерные, то функция рассчитывает угол между осью Х и проекцией вектора, идущего из первой точки во вторую точку, на текущую плоскость построений. ...
Весь этот текст следует просто зачеркнуть. Остальное правильно.

Получение координат точки, лежащей на середине расстояния по прямой, между двумя точками:

Получение координат точки лежащей от точки P1 на расстоянии L в направлении точки P2:

Получение единичного вектора по двум точкам:

Функция EULER-XY
Вычисление углов Эйлера, определяющих разворот ПСК относительно МСК.
по двум векторам направления осей X и Y ПСК.

Функция EULER-Z
Вычисление углов Эйлера, определяющих разворот ПСК относительно МСК.
по направлением оси Z ПСК.

Функция ORT
Вычисляет орт двумерного или трехмерного вектора из точки 0,0,0 в указанную точку

Функция VXV
Вычисляет векторное произведения векторов.
Возврат: список из трех координат результирующего вектора.

Функция VAV.
Определяет взаимное направление 2х векторов. (к сожалению, вектора задаются как направление
из точки 0,0,0 в указанную точку)
Возврат: число - угол между векторами в радианах [0 ; Pi].


Функция GET-UCS-MATRIX
Вычисляет матрицу прямого или обратного преобразования для использования в ActiveX методе TransformBy.
Аргументы.
Функция получает в качестве 1-го аргумента точку начала мысленной ПСК (ПСК не обязана реально существовать).
В качестве второго и третьего аргументов - векторы осей X и Y ПСК.


Получение векторов Z, -Z, X, -X, Y и -Y ПСК объекта по его нормали и углу поворота

Функция по получению точки вставки и трех векторов объекта

Скалярное произведение векторов, однако!

Вычисление точки, лежащей на прямой, пересекающей плоскость.

Функция вычисления угла между векторами (в градусах и от 0 до 180).

Последний раз редактировалось Supermax, 07.12.2009 в 18:22.
Просмотров: 42490
 
Непрочитано 26.11.2009, 19:26
#81
Елпанов Евгений

программист
 
Регистрация: 20.12.2005
Москва
Сообщений: 1,439
Отправить сообщение для Елпанов Евгений с помощью Skype™


Supermax,
1. без матриц нельзя описать поворот в 3д.
2. а если все это проделать не с многострочным текстом, а с другим примитивом, например блоком?

Цитата:
Далее: переходим в вид спереди (Front)
Командой _Rotate крутим наш текст (он еле заметная линия) по часовой на 20 градусов и возвращаемся в план (вид сверху).
А как бы ты сам описал углы поворота и вектор нормали для примитива, который повернут вокруг оси Y в мировой системе координат, а потом еще и вокруг оси Z причем сам примитив создан не в мировой системе координат и второй поворот был вообще не соосен ни с какими ортами внутренней системы координат примитива?

По поводу многострочного текста, я уже говорил, сначала сделай, чтоб при зеркалировании, текст отображался зеркально, а потом рассказывай про эксперименты с текстом - автокад пытается правильно отобразить текст...
__________________
Чем гениальнее ваш план, тем меньше людей с ним будут согласны.
/Сунь Цзы/

Последний раз редактировалось Елпанов Евгений, 26.11.2009 в 19:33.
Елпанов Евгений вне форума  
 
Непрочитано 26.11.2009, 19:29
#82
zamtmn

КИПиА
 
Регистрация: 21.03.2005
Tyumen
Сообщений: 1,352
<phrase 1=


>>Чего, чего?
вру, это угол))
>>Это где выше? Ссылочку плииз.
пост №47 + разде arbitrary axis algorithm из dxf reference
zamtmn вне форума  
 
Непрочитано 26.11.2009, 19:34
#83
Pastor

это только кличка
 
Регистрация: 22.10.2006
Москва
Сообщений: 252


DXF пара 50 - это угол чистого вращения (тот самый "от Эйлера").
Система координат объекта (СКО, она же OCS) представляет собой следующее:
1. Начало совпадает с 000 МСК.
2. Направление Z совпадает с вектором нормали из 210 пары.
3. Ось X всегда лежит в плоскости XY МСК, а её направление вычисляется, как векторное произведение оси Z МСК и вектора нормали объекта. Т.е мысленно вращаем кратчайшим образом Z МСК до совпадения с вектором нормали и по правилу правого винта получаем направление X СКО.
4. Ось Y CКО однозначно определяется через Z и X так, чтобы образовалась правая тройка векторов.
Вот и вся математика.
Теперь пример. Возьмем текст, лежащий в плоскости XY МСК с нулевым углом поворота (чистого вращения). Если его "взять" за конец нормали и слегка "наклонить влево" то оси СКО изменят свое направление. Ось Z - это нормаль, которую мы "слегка наклонили влево". Ось X вычисляется как векторное произведение (Z МСК * нормаль) и смотрит в данном случае строго вниз ( -Y МСК). В этой новой системе координат объекта текст оказывается повернут относительно оси X СКО на 90 градусов. Поэтому и в паре 50 оказывается новое значение согласованное с новой СКО.
__________________
...в шее моей жилы железные, и лоб мой - медный...
Pastor вне форума  
 
Непрочитано 26.11.2009, 19:43
#84
zamtmn

КИПиА
 
Регистрация: 21.03.2005
Tyumen
Сообщений: 1,352
<phrase 1=


>>3. Ось X всегда лежит в плоскости XY МСК, а её направление вычисляется, как векторное произведение оси Z МСК и вектора нормали объекта
не совсем так, используется arbitrary axis algorithm.
углы Эйлера удобны когда надо делать интерполяцию вращения. всерано когда надо конкретно считать - их прибется переводить в матричную форму

Последний раз редактировалось zamtmn, 26.11.2009 в 19:54.
zamtmn вне форума  
 
Непрочитано 26.11.2009, 20:25
#85
Pastor

это только кличка
 
Регистрация: 22.10.2006
Москва
Сообщений: 252


Цитата:
чему равно векторное произведение (0,0,1)*(0,0,1)?
В этом особом случае СКО принимается совпадающим с МСК и считать ничего не требуется. Так же особым является случай, когда нормаль противонаправлена оси Z МСК. Тогда ось X СКО надо принять (-1, 0, 0) .

Цитата:
углы Эйлера удобны когда надо делать интерполяцию вращения. всерано когда надо конкретно считать - их прибется переводить в матричную форму
Углы Эйлера я использовал в приложении под названием QProfile для подзадачи переноса вхождений блоков из пространства модели в пространство листа. Это приложение есть здесь на сайте в архиве и возможно вам даже о нем известно. Там как раз надо было "конкретно считать" и углы Эйлера оказались очень к месту. Код приложения открытый и можно посмотреть, если интересно (конкретно - это файл SolProfiler.lsp).
__________________
...в шее моей жилы железные, и лоб мой - медный...
Pastor вне форума  
 
Автор темы   Непрочитано 26.11.2009, 21:00
#86
Supermax

Руководитель фирмы
 
Регистрация: 28.03.2007
Москва
Сообщений: 1,831
Отправить сообщение для Supermax с помощью Skype™


Pastor, О! Это уже конкретный базар пошел! Жму пять!
Буду завтра разбираться и тщательно вникать.

zamtmn, с твоими мат. примерами тоже. Тебе тоже спасибо за помощь.

Елпанов Евгений,
Цитата:
... По поводу многострочного текста, я уже говорил, сначала сделай, чтоб при зеркалировании, текст отображался зеркально, а потом рассказывай про эксперименты с текстом - автокад пытается правильно отобразить текст...
Ну че ты с этим отзеркаливанием пристал? Текст тут совсем не причем. Это команда его обратно переворачивает. А текст можно как угодно перевернуть. Только если это делать тупо, прямо через изменение Rotation, надо учитывать, что Автокад, получая указание нормали, в зависимости от того, какое это указание, вращает ПСК объекта. Чтобы наклонить нормаль чуть-чуть влево не меняя расположения объекта надо оказывается задать ему при этом угол 90 градусов! Слава богу при изменении нормали, из-за этих наворотов Автокад сам углы пересчитывает.
Всегда, поворачивая объект вокруг нормали, надо считывать существующий угол и прибавлять к нему нужное значение поворота, а не заменять тупо одно на другое.

Ладно, на сабантуй прийду с ноутбуком. Там и пообщаемся. 19-00 буду.
Supermax вне форума  
 
Непрочитано 27.11.2009, 13:06
#87
zamtmn

КИПиА
 
Регистрация: 21.03.2005
Tyumen
Сообщений: 1,352
<phrase 1=


>>В этом особом случае СКО принимается совпадающим с МСК и считать
>>ничего не требуется. Так же особым является случай, когда нормаль
>>противонаправлена оси Z МСК. Тогда ось X СКО надо принять (-1, 0, 0) .

А если нормаль чуть чуть отличается от 0,0,1 ну совсем чуток чуть больще чем погрешность. Получится что Вы перемножите почти паралельные вектора и результат будет неверным.
поэтому делается так:
Цитата:
If (abs (Nx) < 1/64) and (abs (Ny) < 1/64) then
Ax = Wy X N (where “X” is the cross-product operator).
Otherwise,
Ax = Wz X N.
Scale Ax to unit length.
цитата из acad_dxf.chm
zamtmn вне форума  
 
Непрочитано 27.11.2009, 23:11
#88
Pastor

это только кличка
 
Регистрация: 22.10.2006
Москва
Сообщений: 252


Цитату не понял. Равно как и не понял проблему.
Вот функция, вычисляющая векторное произведение.
Если результат слишком близок к (0 0 0), то функция принимает решение, что вектора коллинеарны и возвращает nil.
Код:
[Выделить все]
; V*V.
; Функция вычисления векторного произведения векторов.
; Возврат: список из 3х чисел: трех координат результирующего вектора.
; Если вектора коллинеарны - возвращает nil.
(defun v*v (v1 v2 / res )
  (setq res
	 (list
	   (- (* (cadr v1)(caddr v2)) (* (caddr v1)(cadr v2))); координата X (в МСК).
	   (- (* (caddr v1)(car v2)) (* (car v1)(caddr v2))); координата Y (в МСК).
	   (- (* (car v1)(cadr v2)) (* (cadr v1)(car v2))); координата Z (в МСК).
	 ); return.
  ); setq.
  (if (equal res '(0.0 0.0 0.0) 1e-12) nil res); return.
); end defun.
В данном случае точность сравнения принята 1е-12.
__________________
...в шее моей жилы железные, и лоб мой - медный...
Pastor вне форума  
 
Непрочитано 28.11.2009, 12:21
#89
zamtmn

КИПиА
 
Регистрация: 21.03.2005
Tyumen
Сообщений: 1,352
<phrase 1=


>>Цитату не понял. Равно как и не понял проблему.
Вы говорите что:
Цитата:
3. Ось X всегда лежит в плоскости XY МСК, а её направление вычисляется, как векторное произведение оси Z МСК и вектора нормали объекта.
Это не совсем так, если и X и Y нормали < 1/64 то ось x - векторное произведение YМСК и нормали, если это не учесть - вращение будет глючить при нормали близкой 0,0,+-1.
"близкой" = X и Y нормали < 1/64. конечно в жизни такие нормали бывают не часто, но бывают
zamtmn вне форума  
 
Непрочитано 29.11.2009, 16:48
#90
Pastor

это только кличка
 
Регистрация: 22.10.2006
Москва
Сообщений: 252


Признаю свою ошибку.
AutoCAD вводит четко определенные правила при вычислении СКО для векторов нормали близких к оси Z МСК. Как указывал выше zamtmn, всё описано в acad_dxf.chm.
Кстати, число 1/64 не такое уж и маленькое. В пересчете на градусы отклонения от Z МСК это между 0.8 и 0.9.

>>zamtmn
Спасибо за вашу настойчивость. Лоб то у меня медный
__________________
...в шее моей жилы железные, и лоб мой - медный...
Pastor вне форума  
 
Автор темы   Непрочитано 29.11.2009, 21:48
#91
Supermax

Руководитель фирмы
 
Регистрация: 28.03.2007
Москва
Сообщений: 1,831
Отправить сообщение для Supermax с помощью Skype™


Вставлю свои пять копеек.
Замечу, что функция перемножения векторов никогда, подчеркивю НИКОГДА не должна возвращать nil!
Если вектора практически слились в одну линию, то надо чтобы функция все равно возвращала какой-то вектор.
В частности, если мы перемножаем нормаль на вектор Z МСК, то функция вырождается в:

Код:
[Выделить все]
(defun v*z (v1 / res )
  (setq res
	 (list
	  (cadr v1); координата X (в МСК).
	   (- 0 (car v1)); координата Y (в МСК).
	   0.0; координата Z (в МСК).
	 ); return.
  ); setq.
  (if (equal res '(0.0 0.0 0.0) 1e-12) nil res); return.
); end defun.
Остается вместо nil вставить вектор. (1.0 0.0 0.0)?

Результирующий вектор должен быть перпендикулярен нормали. То есть он лежит в плоскости XY МСК, но перпендикулярен и оси Z МСК и нормали одновременно. Тогда мне понятно как отложить угол от этого вектора к оси X СКО.

Y равна перевернутому X нормали, а X - Y нормали. Получается 90 градусов.
Вот так - правильно!

Смущает одно, надо продлевать значения X и Y результирующего вектора до точки на единичной окружности. Чтобы функция не бесконечно малые числа возвращала, а путевый единичный вектор.

Последний раз редактировалось Supermax, 29.11.2009 в 22:30.
Supermax вне форума  
 
Непрочитано 29.11.2009, 22:04
#92
Елпанов Евгений

программист
 
Регистрация: 20.12.2005
Москва
Сообщений: 1,439
Отправить сообщение для Елпанов Евгений с помощью Skype™


Цитата:
Сообщение от Supermax Посмотреть сообщение
Остается вместо nil вставить вектор. (1.0 0.0 0.0)?
тогда уж лучше:
Код:
[Выделить все]
(list (cadar vl)(caddar vl)(caar vl))
__________________
Чем гениальнее ваш план, тем меньше людей с ним будут согласны.
/Сунь Цзы/
Елпанов Евгений вне форума  
 
Автор темы   Непрочитано 29.11.2009, 22:10
#93
Supermax

Руководитель фирмы
 
Регистрация: 28.03.2007
Москва
Сообщений: 1,831
Отправить сообщение для Supermax с помощью Skype™


Код:
[Выделить все]
(list (cadar vl)(caddar vl)(caar vl))
Это ты как (cadar vl) сделаешь? Ты сначала car делаешь, а потом cdr? Изчего? и все остальное - издеваешься?
Supermax вне форума  
 
Непрочитано 29.11.2009, 22:53
#94
Елпанов Евгений

программист
 
Регистрация: 20.12.2005
Москва
Сообщений: 1,439
Отправить сообщение для Елпанов Евгений с помощью Skype™


Supermax, Действительно, невнимательно смотрел код...
В данном случае, я хотел сказать - если необходимо всегда давать вектор - значит надо давать, но это не значит, что при ошибке всегда давать какой то заранее заданный. Такой подход, в будущем приведет к очень сложно находимым ошибкам...
__________________
Чем гениальнее ваш план, тем меньше людей с ним будут согласны.
/Сунь Цзы/
Елпанов Евгений вне форума  
 
Непрочитано 30.11.2009, 09:39
#95
zamtmn

КИПиА
 
Регистрация: 21.03.2005
Tyumen
Сообщений: 1,352
<phrase 1=


>>Остается вместо nil вставить вектор. (1.0 0.0 0.0)?
вообщето для паралельных векторов результат долженбыть (0.0 0.0 0.0) по определению векторного произведения. разруливать паралельность нужно вызывающей программой, а не программой умножения.
zamtmn вне форума  
 
Автор темы   Непрочитано 03.12.2009, 14:38
#96
Supermax

Руководитель фирмы
 
Регистрация: 28.03.2007
Москва
Сообщений: 1,831
Отправить сообщение для Supermax с помощью Skype™


Я считаю, что надо сначала сравнивать векторы на паралельность, а потом решать что с этим делать. И как узнать при каких обстаятельствах и как определить паралельны они или нет?
Функция не доработана. А надо.

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

Последний раз редактировалось Supermax, 03.12.2009 в 14:48.
Supermax вне форума  
 
Непрочитано 03.12.2009, 15:31
#97
zamtmn

КИПиА
 
Регистрация: 21.03.2005
Tyumen
Сообщений: 1,352
<phrase 1=


универсальный способ проверить на паралльность - посчитать векторное произведение

>>Очень надо вычислять точку пересечения прямой и плоскости. Плоскость по трем точкам, а прямая по двум.
вся необходимая математика: http://algolist.ru/maths/geom/index.php
перекатать это на лиспе думаю труда не составть

Последний раз редактировалось zamtmn, 03.12.2009 в 15:40.
zamtmn вне форума  
 
Автор темы   Непрочитано 03.12.2009, 16:25
#98
Supermax

Руководитель фирмы
 
Регистрация: 28.03.2007
Москва
Сообщений: 1,831
Отправить сообщение для Supermax с помощью Skype™


Чтобы туда-сюда не лазить сюда перенес суть.
Цитата:
Пересечение: Прямая(или отрезок) и плоскость

Плоскость задана тремя точками, прямая( или отрезок) начальной и конечными точками.

Очевидно, эта задача, как и многие подобные ей, может быть решена путем составления системы. Хотелось бы предложить более геометричный метод, который гораздо удобней в большинстве случаев.

Будем обозначать A,B,C - точки плоскости, X,Y - точки прямой(концы отрезка), SP - скалярное произведение, VP - векторное произведение. O - искомое множество точек пересечения

N = VP ( B - A, C - A )
N = N / | N | - нормаль к плоскости // в принципе это можно и не делать
V = A - X
// расстояние до плоскости по нормали
d = SP ( N, V )
W = Y - X
// приближение к плоскости по нормали при прохождении отрезка
e = SP ( N, W )

if( e!=0 )
O = X + W * d/e; // одна точка
else if( d==0)
O =X + W * (anything) // прямая принадлежит плоскости
else
O = empty; // прямая параллельна плоскости


Если хочешь быть уверен, что плоскость пересекает не только прямая, но и отрезок, можно проверить условие SP ( X - O, Y - O ) <=0
И так:
Код:
[Выделить все]
(defun point-suppression-plane (a b c x y)
(setq b-a (mapcar '(lambda (w r) (- w r)) b a))
(setq c-a (mapcar '(lambda (w r) (- w r)) c c))
(setq n (v*v b-a c-a))
(setq n (mapcar '(lambda (w) (sgrt (* w w))) n) ; хотя, как говорят этого можно и не делать
(setq v (mapcar '(lambda (w r) (- w r)) a x))
(setq d (3d_angw1w2 n v))
(setq w (mapcar '(lambda (w r) (- w r)) y x))
(setq e (3d_angw1w2 n w))

дальше потом допишу
А вот тут проблема с перемножением векторов. Существующая функция в случае паралельности векторов должна выдавать что? (0.0 0.0 0.0)?

Ладно, переделываем функцию перемножения на классику.
Код:
[Выделить все]
; V*V.
; Функция вычисления векторного произведения векторов.
; Возврат: список из 3х чисел: трех координат результирующего вектора.
; Если вектора коллинеарны - возвращает nil.
(defun v*v (v1 v2 / res )
  (setq res
	 (list
	   (- (* (cadr v1)(caddr v2)) (* (caddr v1)(cadr v2))); координата X (в МСК).
	   (- (* (caddr v1)(car v2)) (* (car v1)(caddr v2))); координата Y (в МСК).
	   (- (* (car v1)(cadr v2)) (* (cadr v1)(car v2))); координата Z (в МСК).
	 ); return.
  ); setq.
  (if (equal res '(0.0 0.0 0.0) 1e-12) '(0.0 0.0 0.0) res); return.
); end defun.
А если для ПСК объектов считать придется, то:

Код:
[Выделить все]
(if (= (v*v a1 b1) '(0.0 0.0 0.0)) '(1.0 0.0 0.0) (v*v a1 b1))

Последний раз редактировалось Supermax, 03.12.2009 в 17:57.
Supermax вне форума  
 
Непрочитано 03.12.2009, 16:58
#99
Елпанов Евгений

программист
 
Регистрация: 20.12.2005
Москва
Сообщений: 1,439
Отправить сообщение для Елпанов Евгений с помощью Skype™


проверить параллельность двух плоскостей можно проще, по векторам:
Код:
[Выделить все]
(setq v1 '(0. 0. 1.) v2 '(0. 1. 2.))
(and(inters '(0. 0. 0.) v1 '(0. 0. 0.) v2))
короче, если вектора пересекаются в общей точке - значит и плоскости пересекаются...
__________________
Чем гениальнее ваш план, тем меньше людей с ним будут согласны.
/Сунь Цзы/
Елпанов Евгений вне форума  
 
Непрочитано 03.12.2009, 17:28
#100
zamtmn

КИПиА
 
Регистрация: 21.03.2005
Tyumen
Сообщений: 1,352
<phrase 1=


>>дальше застрял. Угол между векторами надо найти.
дальше не нужно угол искать. нужно поюзать гугл и посмотреть определение скалярного произведения.
можно вот так посчитать:
Цитата:
function scalardot(var v1,v2:GDBVertex):GDBDouble;
begin
result:=v1.x * v2.x + v1.y * v2.y +v1.z*v2.z;
end;
zamtmn вне форума  
Ответ
Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > Тригонометрические функции и векторная алгебра

Размещение рекламы


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Рифмоплетство. Kryaker Разное 554 14.11.2023 11:59
Определение высот рельефа по близлежащим точкам dextron3 Программирование 21 10.11.2011 13:14
Интерполяция между двумя точками postbudka Программирование 27 21.05.2009 10:00
ЮМОР 2006 =) Perezz!! Разное 1122 04.01.2007 00:46
Координаты точки, лежащей на полилинии Al_Taron Программирование 1 27.11.2006 09:45