Тема: Как определить принадлежит ли точка отрезку или нет?
Как определить принадлежит ли точка отрезку или нет?
Информационный портал для профессионалов в области САПР
Вы не вошли. Пожалуйста, войдите или зарегистрируйтесь.
Форумы CADUser → Программирование → LISP → Как определить принадлежит ли точка отрезку или нет?
Страницы 1
Чтобы отправить ответ, вы должны войти или зарегистрироваться
Как определить принадлежит ли точка отрезку или нет?
Точка принадлежит отрезку, если сумма расстояний от этой точки до конечных точек отрезка равна длине отрезка.
Очень интерестно проходит ли такая проверка.
Я в свое время для похожей задачи по двум точкам отрезка задавал уравнение прямой и подставлял в него координаты точки. Теоретически если точка на прямой уравнение обнуляется (aX+bY+c=0) на практике условие проходило если отрезок горизонтален или вертикален (точку получал указанием с привязкой к ближнему), ели нет погрешность приходилось учитывать (при конечной точности вычислений в данном случае это неизбежно) .
Если устроит попробуйте использовать
функцию (vlax-curve-getParamatPoint <кривая> <точка>).
Если вернёт nil значит точка не лежит на кривой.
У Полещука написано <кривая> - VLA-объект,
но как показывает практика можно и имя примитива.
Когда-то (в AutoCAD10) выходил из положения так :
(setq Nabor (ssget "_C" t1 t1))
,- где t1 - координаты точки [например, '(150 175 0)],
а затем, перебирал объекты, попавшие в набор "Nabor", на предмет наличия среди них того самого отрезка...
Я в свое время точно также как и AY пытался решить эту задачу на основе линейных уравнений. Оказалось, что камнем преткновения является погрешность вычислений. В итоге, метод работает ненадежно и неустойчиво. По-видимому, сама постановка вопроса -Точка принадлежит линии - при переводе в практическую плоскость нуждается в переосмыслении. А что есть прямая (линия), ведь это не более чем выдумка античных математиков...ведь она не имеет толщины, и следовательно - не существует. Я понимаю, все это звучит несколько академически, однако вопрос надо решать!
Давайте считать линией полосу конечной ширины, и при постановке задачи указывать эту ширину. Интересно было бы услышать мнение профессиональных математиков, например, специалистов по теории множеств.
Тоже недавно делал проверку принадлежности точки сфере. Естественно сравнение через EQUAL, смотря какая точность нужна...
Есть еще идея. Существует функция vlax-curve-getDistAtPoint <кривая> <точка> которая вычисляет расстояние между начальной точкой кривой (а в нашем случае отрезка) до точки на кривой. В случае если точка не лежит на кривой она возвратит Nil.
Public Function ТочкаНаПрямой(dblСписокКоордПрямой As Variant, XCoordТочки As Double, YCoordТочки As Double) As Boolean
Dim РасстояниеДоТочки As Double, РасстояниеПослеТочки As Double, ДлинаПрямой As Double
РасстояниеДоТочки = VBA.Sqr((XCoordТочки - dblСписокКоордПрямой(1)) ^ 2 + (YCoordТочки - dblСписокКоордПрямой(2)) ^ 2)
РасстояниеПослеТочки = VBA.Sqr((dblСписокКоордПрямой(3) - XCoordТочки) ^ 2 + (dblСписокКоордПрямой(4) - YCoordТочки) ^ 2)
ДлинаПрямой = VBA.Sqr((dblСписокКоордПрямой(3) - dblСписокКоордПрямой(1)) ^ 2 + (dblСписокКоордПрямой(4) - dblСписокКоордПрямой(2)) ^ 2)
If VBA.Round(РасстояниеДоТочки + РасстояниеПослеТочки, 7) = VBA.Round(ДлинаПрямой, 7) Then
'Точка находится на прямой
ТочкаНаПрямой = True
Else
'Точка находится вне прямой (ответ = расстояние от конца прямой до точки)
' ТочкаНаПрямой = (РасстояниеДоТочки + РасстояниеПослеТочки - ДлинаПрямой) / 2
ТочкаНаПрямой = False
End If
End Function
Эта функция работает без видимых и заметных сбоев уже долгое время. Весь секрет в том, что надо задавать как все нормальные люди точность своих вычислений, а не пытаться выполнить свою задачу с точностью до микрона там где требуется точность максимум до милиметра, и 7 знаков после запятой при единицах измерения мм вполне достаточно. Можете повысить точность до 12 чисел и выше, однако математические способности VBA уже начинают выдавать вместо 1 число 0,9999999999999999999999999999 и выражение 1=1 (при определёном задании и способах получения переменых) уже может не являться истиной. Прежде всего надо знать пределы математических возможностей программы с которой вы работаете и не тратить время на излишнюю точность а выдавать продукцию.
Как уже писал, при теоретическом подходе учет пргрешности неизбежен, однако предположу, что функции (vlax-* могут контролировать и учитывать ее и выдавать достоверный результат. Может ли кто-нибудь подтвердить такое предположение?
*1.2 Аналитическая геометрия на плоскости.*
_1.2.1 Основные формулы в Декартовой системе координат._
P1(x1, y1), P2(x2, y2), P3(x3, y3), P4(x4, y4)
- Расстояние:
d(P1, P2) = sqrt((x1-x2)^2 + (y1-y2)^2)
- Угол между двумя веторами P1P2 P3P4:
(x2-x1)(x4-x3) + (y2-y1)(y4-y3) (P1P2, P3P4)
cos(al) = --------------------------------- = -------------------
d(P1, P2)*d(P3, P4) d(P1, P2)*d(P3, P4)
(x2-x1)(y4-y3) - (x4-x3)(y2-y1) [P1P2, P3P4]
sin(al) = --------------------------------- = ------------------
d(P1, P2)*d(P3, P4) d(P1, P2)*d(P3, P4)
(x2-x1)(y4-y3) - (x4-x3)(y2-y1) [P1P2, P3P4]
tg (al) = --------------------------------- = ------------------
(x2-x1)(x4-x3) + (y2-y1)(y4-y3) (P1P2, P3P4)
- Координаты x, y точки P, делящей P1P2 в отношении m/n = p/1
mx2 + nx1 x1 + qx2
x = --------- = ---------;
n + m 1 + p
my2 + ny1 x1 + qx2
y = --------- = ---------;
m + n 1 + p
- Соответственно, если P - середина (n=m), то
x2 + x1 y2 + y1
x = -------; y = -------;
2 2
- Координаты x, y точки P, делящей P1P2 в отношении m/n = p/1
mx2 + nx1 x1 + qx2
x = --------- = ---------;
n + m 1 + p
my2 + ny1 x1 + qx2
y = --------- = ---------;
m + n 1 + p
- Соответственно, если P - середина (n=m), то
x2 + x1 y2 + y1
x = -------; y = -------;
2 2
- Координаты x, y точки P, делящей P1P2 в отношении m/n = p/1
x = (mx2 + nx1)/(n + m)=(x1 + qx2)/(1 + p)
y = (my2 + ny1)/(n + m)=(y1 + qy2)/(1 + p)
съезжают дроби...
- Соответственно, если P - середина (n=m), то
x = (x2 + x1)/2 ; y = (y2 + y1)/2
В моей задаче рассматривалось взаимодействие множества линий на плоскости (чертежа), в частности, исследовался вопрос о наложении линий. Пришлось пойти на то, что "точка"
определялась как некая область, размеры которой зависят от погрешности вычислений. При зтом - увеличение точности
приводило к неустойчивости, слишком маленькую точку общую для двух линий программа не ловила, а снижение точности приводило к размытости критериев, программа на выполняла своих функций, т.е. возникали ложные наложения. В итоге, оптимальный вариант так и не был найден.
;| ф-ция проверяет принадлежит ли точка отрезку или нет;
возвращает t - если принадлежит и nil - если нет
аргументы: p - точка, lps - список из 2-х точек отрезка eps - допуск погрешности
1 - считаем расстояние (d) от точки до отрезка и сравниваем с eps
расстояние меньше eps
2 - Точка находиться между двумя перпендикулярами, проведенными
через концы отрезка (используется скалярное произведение)
создал - Уланов О. В. 6/16/04 10:21 PM дома;-) .
с помощью http://faqs.org.ru/science/geometry_faq.htm
|;
(defun pts (p lps)
(setq x (car p) y (cadr p)
x1 (caar lps) y1 (cadar lps)
x2 (caadr lps) y2 (cadadr lps)
eps 10e-10
d (/(sqrt(abs(-(*(- x x1)(- y2 y1))(*(- y y1)(- x2 x1)))))(sqrt(abs(+(- x2 x1)(sqrt(abs(- y2 y1)))))))
2p (*(+(*(- x x1)(- x2 x1))(*(- y y1)(- y2 y1)))(+(*(- x x2)(- x2 x1))(*(- y y2)(- y2 y1))))
); setq
(cond
((> d (sqrt eps)) nil)
((< 2p eps) t)
(t nil)
); cond
); defun
(defun c:pbs (/)
(while
(setq p (getpoint "\nВыдели точку!!!")
en (entget(car(entsel "\nУкажи линию!!!")))
lps (list(cdr(assoc 10 en))(cdr(assoc 11 en)))
); setq
(cond
((eq(pts p lps)t)(print "\nТочка лежит на отрезке!!!"))
((eq(pts p lps)nil)(print "\nТочка не лежит на отрезке!!!"))
(t nil)
); cond
); while
); defun
(defun isOnLine (_начальная _конечная _точка _допуск) (apply '(lambda (_до_начальной _длина_отрезка _до_конечной) (equal (+ _до_начальной _до_конечной) _длина_отрезка _допуск)) (mapcar 'distance (list _точка _начальная _точка) (list _начальная _конечная _конечная))) )
Страницы 1
Чтобы отправить ответ, вы должны войти или зарегистрироваться
Форумы CADUser → Программирование → LISP → Как определить принадлежит ли точка отрезку или нет?
Форум работает на PunBB, при поддержке Informer Technologies, Inc