Проецирование точки

Автор Тема: Проецирование точки  (Прочитано 15479 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Тема содержит сообщение с Решением. Нажмите здесь чтобы посмотреть его.

Оффлайн 1958Автор темы

  • ADN OPEN
  • **
  • Сообщений: 93
  • Карма: 0
Проецирование точки
« : 06-06-2017, 13:52:46 »
Не смог найти ответа на интересующий меня вопрос.
Имеется поверхность из 3DFACE на отдельном слое. Имеется точка с координатами x,y.
Как спроецировать точку на поверхность, чтобы получить отметку? Как это можно оформить лиспом?

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13886
  • Карма: 1788
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Проецирование точки
« Ответ #1 : 06-06-2017, 13:55:15 »
Имеется поверхность из 3DFACE на отдельном слое.
Это один 3DFACE или их много и поверхность создана из них?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн 1958Автор темы

  • ADN OPEN
  • **
  • Сообщений: 93
  • Карма: 0
Re: Проецирование точки
« Ответ #2 : 06-06-2017, 15:34:42 »
3DFACE целая сеть и поверхность создана из них

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13886
  • Карма: 1788
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Проецирование точки
« Ответ #3 : 06-06-2017, 15:40:14 »
3DFACE целая сеть и поверхность создана из них
Значит сначала по координатам X и Y точки нужно найти ту 3DFACE, на которую эта точка проецируется, а затем выполнить проекцию, т.е. найти пересечение вертикальной прямой проходящей через точку (X,Y,0) и плоскости совпадающей с плоскостью 3DFACE (надеюсь, что у 3DFACE только три вершины, т.к. в противном случае она не плоская). Это элементарная задача аналитической геометрии. Специальных готовых алгоритмов для её решения в AutoLisp/VisualLisp нет. Так что нужно их самому написать или поискать в интернете.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн 1958Автор темы

  • ADN OPEN
  • **
  • Сообщений: 93
  • Карма: 0
Re: Проецирование точки
« Ответ #4 : 06-06-2017, 15:41:02 »
В принципе у меня решение есть, но хотелось бы покороче.

Код - Auto/Visual Lisp [Выбрать]
  1. (defun c:z_3d (pt / 1_3d) ; Определение координат двухмерной точки pt
  2.  (setq x    (nth 0 pt)
  3.        y    (nth 1 pt)
  4.        1_3d nil
  5.        i    0
  6.        ii   0
  7.  )
  8.  (setq 1_3d (ssget "_X" '((0 . "3DFACE") (8 . "ТРИАНГУЛЯЦИЯ"))))
  9.  (while (and (< i (sslength 1_3d)) (= ii 0))
  10.   (setq pt1 (cdr (assoc 10 (entget (ssname 1_3d i))))
  11.         pt2 (cdr (assoc 12 (entget (ssname 1_3d i))))
  12.         pt3 (cdr (assoc 13 (entget (ssname 1_3d i))))
  13.         x1  (nth 0 pt1)
  14.         y1  (nth 1 pt1)
  15.         z1  (nth 2 pt1)
  16.         x2  (nth 0 pt2)
  17.         y2  (nth 1 pt2)
  18.         z2  (nth 2 pt2)
  19.         x3  (nth 0 pt3)
  20.         y3  (nth 1 pt3)
  21.         z3  (nth 2 pt3)
  22.   )
  23.   (if (> x2 x1)
  24.    (setq xmax x2
  25.          xmin x1
  26.    )
  27.    (setq xmax x1
  28.          xmin x2
  29.    )
  30.   )
  31.   (if (> x3 xmax)
  32.    (setq xmax x3)
  33.   )
  34.   (if (< x3 xmin)
  35.    (setq xmin x3)
  36.   )
  37.   (if (> y2 y1)
  38.    (setq ymax y2
  39.          ymin y1
  40.    )
  41.    (setq ymax y1
  42.          ymin y2
  43.    )
  44.   )
  45.   (if (> y3 ymax)
  46.    (setq ymax y3)
  47.   )
  48.   (if (< y3 ymin)
  49.    (setq ymin y3)
  50.   )
  51.   (if (and (> x xmin) (< x xmax))
  52.    (progn (if (and (> y ymin) (< y ymax))
  53.            (setq ii (+ ii 1))
  54.           )
  55.    )
  56.   )
  57.   (setq i (+ 1 i))
  58.  )
  59.  (setq A (+ (+ (* y1 (- z2 z3)) (* y2 (- z3 z1))) (* y3 (- z1 z2)))
  60.        B (+ (+ (* z1 (- x2 x3)) (* z2 (- x3 x1))) (* z3 (- x1 x2)))
  61.        C (+ (+ (* x1 (- y2 y3)) (* x2 (- y3 y1))) (* x3 (- y1 y2)))
  62.        D (* -1
  63.             (+ (+ (* x1 (- (* y2 z3) (* y3 z2)))
  64.                   (* x2 (- (* y3 z1) (* y1 z3)))
  65.                   (* x3 (- (* y1 z2) (* y2 z1)))
  66.                )
  67.             )
  68.          )
  69.  )
  70.  (setq z (/ (- (- (* -1 D) (* A x)) (* B y)) C)
  71.        pt (list (nth 0 pt) (nth 1 pt) z)) ;трехмерная точка
  72. )
« Последнее редактирование: 06-06-2017, 16:25:00 от Александр Ривилис »

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13886
  • Карма: 1788
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Проецирование точки
« Ответ #5 : 06-06-2017, 16:15:25 »
1. Напоминаю про правила форматирования кода на форуме (у меня в подписи).
2. Короче не будет, так как встроенного алгоритма (в отличие от ObjectARX/AutoCAD .NET API нет).
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн 1958Автор темы

  • ADN OPEN
  • **
  • Сообщений: 93
  • Карма: 0
Re: Проецирование точки
« Ответ #6 : 07-06-2017, 09:15:06 »
Ладно, а если я предварительно создам список координат треугольников в виде ((x y) z), например список координат трех треугольников:

((((1.22039e+007 4.28423e+006) 336.62) ((1.22038e+007 4.28422e+006) 336.65) ((1.22038e+007 4.2842e+006) 336.71))
(((1.22039e+007 4.28419e+006) 336.74) ((1.22039e+007 4.28423e+006) 336.62) ((1.22038e+007 4.2842e+006) 336.71))
(((1.22039e+007 4.2842e+006) 336.68) ((1.22039e+007 4.28423e+006) 336.62) ((1.22039e+007 4.28419e+006) 336.74))),

как узнать в какой треугольник попадает выбранная точка (x y)?
Т.е. нужен короткий алгоритм:
1. Выбираем из списка первый треугольник ((1.22039e+007 4.28423e+006) 336.62) ((1.22038e+007 4.28422e+006) 336.65) ((1.22038e+007 4.2842e+006) 336.71))
2. Определяем попадает ли точка в этот треугольник
3. Если попадает, вычисляем отметку точки, если нет - переход к пункту 1 со следующим треугольником.

Вся загвоздка в пункте 2.

Оффлайн trir

  • ADN Club
  • ****
  • Сообщений: 475
  • Карма: 63
Re: Проецирование точки
« Ответ #7 : 07-06-2017, 12:12:53 »
Есть куча алгоритмов определения принадлежности точки полигону, но в данном случае можно по формуле  sign((ax + by + c)/sqrt(a^2+b^2)) определить положение точки относительно рёбер треугольника (совпадает для всех рёбер, если точка внутри), тут важен порядок обхода рёбер

Оффлайн 1958Автор темы

  • ADN OPEN
  • **
  • Сообщений: 93
  • Карма: 0
Re: Проецирование точки
« Ответ #8 : 07-06-2017, 12:44:01 »
Наверно, лучше использовать набор.
Т.е. рисуем точку, потом выбираем ее (setq ptn (ssget "_CP" pt_list)).  pt_list - список плоских (x y) координат вершин текущего треугольника.
Если ptn не nil, то точка попала в текущий треугольник.

Оффлайн Алексей Кулик

  • Administrator
  • *****
  • Сообщений: 1116
  • Карма: 173
Re: Проецирование точки
« Ответ #9 : 07-06-2017, 14:46:44 »
И каждый раз выполнять зум, панорамирование и регенерацию экрана - чтобы точки контура гарантированно в него попали?
Все, что сказано - личное мнение.

Правила форума существуют не просто так!

Приводя в сообщении код, не забывайте про его форматирование!

Отмечено как Решение 1958 07-06-2017, 16:40:35

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13886
  • Карма: 1788
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Проецирование точки
« Ответ #10 : 07-06-2017, 14:51:36 »
Наверно, лучше использовать набор.
Т.е. рисуем точку, потом выбираем ее (setq ptn (ssget "_CP" pt_list)).  pt_list - список плоских (x y) координат вершин текущего треугольника.
Если ptn не nil, то точка попала в текущий треугольник.
Не обижайтесь, но это самый худший алгоритм из всех, которые можно было бы придумать. Даже объяснять не буду насколько он будет ненадежный, медленный и т.д.
Посмотрите вот этот алгоритм для определения находится ли точка внутри контура (треугольник - это тоже контур из трёх вершин): http://forum.dwg.ru/showpost.php?p=1538777&postcount=62
Или этот: http://www.cadtutor.net/forum/showthread.php?39199-Identify-a-polyline-by-a-point-inside-this-polyline&p=263330&viewfull=1#post263330
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн trir

  • ADN Club
  • ****
  • Сообщений: 475
  • Карма: 63
Re: Проецирование точки
« Ответ #11 : 07-06-2017, 14:55:35 »
Откуда уши:
Цитировать
По книге Ласло,
"Вычислительная геометрия и компьютерная графика на С++"

Если надо найти треугольник в который попадает точка, то лучше сначала искать в r-дереве...

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13886
  • Карма: 1788
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Проецирование точки
« Ответ #12 : 07-06-2017, 15:15:45 »
Если надо найти треугольник в который попадает точка, то лучше сначала искать в r-дереве...
Согласен, но не видел готового алгоритма R-Tree на Autolisp, что означает или необходимость его написать (вряд ли эта задача по плечу 1958) или использовать готовые алгоритмы на .NET или ObjectARX.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн 1958Автор темы

  • ADN OPEN
  • **
  • Сообщений: 93
  • Карма: 0
Re: Проецирование точки
« Ответ #13 : 07-06-2017, 16:42:02 »

Оффлайн 1958Автор темы

  • ADN OPEN
  • **
  • Сообщений: 93
  • Карма: 0
Re: Проецирование точки
« Ответ #14 : 07-06-2017, 17:15:04 »
Код - Auto/Visual Lisp [Выбрать]
  1. (defun c:coor_3df (/)
  2.  (vl-cmdf "_.-layer" "_SET" "ИИ_ТРИАНГУЛЯЦИЯ_025" "")
  3.  (setq ptn (reverse (cdr (reverse (getpoint "Укажите точку")))) ;координаты точки (x y)
  4.        i   0
  5.  )
  6.  (vl-cmdf "_point" ptn) ;рисуем точку
  7.  (setq ss      (ssget "_X" '((0 . "3DFACE") (8 . "ИИ_ТРИАНГУЛЯЦИЯ_025"))) ;набор 3Д-граней
  8.        ss_3d   nil
  9.        i_trian nil
  10.  )
  11.  (repeat (setq in (sslength ss))
  12.   (setq 1_3d  (ssname ss (setq in (1- in))) ;выбираем треугольник
  13.         1_3   (cdr (assoc 10 (entget 1_3d))) ;координаты (x y z) 1-ой вершины треугольника
  14.         2_3   (cdr (assoc 12 (entget 1_3d))) ;координаты (x y z) 2-ой вершины треугольника
  15.         3_3   (cdr (assoc 13 (entget 1_3d))) ;координаты (x y z) 3-ой вершины треугольника
  16.         s_3d  (list 1_3 2_3 3_3) ;список координат треугольника
  17.         ss_3d (cons s_3d ss_3d) ;добавляем в общий список
  18.   )
  19.  )
  20.  (while (< i (1- (length ss_3d)))
  21.   (setq i_trian (nth i ss_3d)) ;вытаскиваем i-ый треугольник
  22.   (setq i_1 (reverse (cdr (reverse (nth 0 i_trian)))) ; x,y 1-ой вершины
  23.         i_2 (reverse (cdr (reverse (nth 1 i_trian)))) ; x,y 2-ой вершины
  24.         i_3 (reverse (cdr (reverse (nth 2 i_trian)))) ; x,y 3-ой вершины
  25.   )
  26.   (setq pt_list (list i_1 i_2 i_3)) ;список вершин треугольника
  27.   ;выбираем точку многоугольником:
  28.   (setq pt (ssget "_CP" pt_list '((0 . "POINT") (8 . "ИИ_ТРИАНГУЛЯЦИЯ_025"))))
  29.   (if (= (sslength pt) 0) ;если набор пустой
  30.    (setq i (1+ i)) ;переходим к следующему треугольнику
  31.    (setq i (1+ (length ss_3d))) ;нужный треугольник найден, выходим из цикла
  32.   )
  33.  )
  34.  (alert (strcat "вершины треугольника\n" (vl-prin1-to-string i_trian)))
  35.  (entdel (entlast)) ;удаляем точку
  36.  (vl-cmdf "_.-layer" "_SET" "0" "")
  37.  (princ)
  38. )


Если я указываю точку в первом треугольнике, всё нормально. Иначе - ошибка. В чём дело, не пойму.
« Последнее редактирование: 07-06-2017, 18:10:09 от Александр Ривилис »