Скачать NANOCAD Pдгы 8.5
dwg.ru forum rss xml
| Правила | Регистрация | Пользователи | Поиск | Сообщения за день | Все разделы прочитаны |  Справка по форуму |

Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > Поиск минимального расстояния между линейными примитивами

Поиск минимального расстояния между линейными примитивами

Версия для печати
 
Ответ
Опции темы Поиск в этой теме
Непрочитано 30.05.2012, 13:39 #1
Поиск минимального расстояния между линейными примитивами
NEDIS
 
Инженер СКС
 
г. Домодедово МО
Регистрация: 21.08.2009
Сообщений: 72

NEDIS вне форума Вставить имя

Добрый день форумчане!
Задача следующая:
Есть объекты LWPOLYLINE,LINE и POLYLINE. Для каждой пары объектов необходимо найти минимальное расстояние между ними, т.е. отрезок минимальной длины между этими объектами.
Все объекты из линейных элементов.
Есть такое чувство, что закромах Autocad есть что-то подобное функции vla-IntersectWith - получение точек пересечения графических объектов или их продлений.
Помогите с lisp-ом, а то не могу понять с какой стороны подползти.
Пример прикрепил. Красным обозначены решения. Выбрал три типовых пары примитивов для примера.

Вложения
Тип файла: dwg
DWG 2007
Пример.dwg (348.2 Кб, 2094 просмотров)

Просмотров: 4349
 
Непрочитано 30.05.2012, 15:05
#2
Дима_

Продуман
 
Регистрация: 22.02.2007
Питер
Сообщений: 2,837


На Вашем рисунке объекты пересекаються, то есть минимальное расстояние=0, найти можно только ТОЧКУ пересечения - через ту-же IntersectWith
з.ы. все увидел что это трехмерка.
Ну пока ничего кроме долгой и муторной проверки через определенный шаг (например 1% от длинны линии) с последующей "доводкой" до заданной точности, на ум не приходит.
__________________
Когда в руках молоток все вокруг кажется гвоздями.

Последний раз редактировалось Дима_, 30.05.2012 в 15:20.
Дима_ вне форума вставить имя Обратить внимание модератора на это сообщение  
 
Непрочитано 30.05.2012, 16:38
#3
Кулик Алексей aka kpblc
Moderator

LISP, C# (ACAD 200[9,12,13,14])
 
Регистрация: 25.08.2003
С.-Петербург
Сообщений: 34,843


Вроде бы на theswamp.org были какие-то лиспы на поиск минимального расстояния между кривыми. Может, поможет?
__________________

---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума вставить имя Обратить внимание модератора на это сообщение  
 
Непрочитано 31.05.2012, 00:05
#4
Do$

AutoCAD/Civil3D LISP/C#
 
Регистрация: 15.08.2008
Санкт-Петербург
Сообщений: 1,627
Отправить сообщение для Do$ с помощью Skype™


Мне это как-то так представляется.

Метод №1 - аналитический:
Тут надо рассматривать расстояния по методу определения расстояния между скрещивающимися прямыми (см. аналитическую геометрию в пространстве). Объекты исследования - LINE (отрезок) или сегменты объектов POLYLINE и LWPOLYLINE (полилинии).
Самый простой вариант - отрезок с отрезком. Алгоритм для него:
- Проверяем, принадлежат ли отрезкам концы перпендикуляра к скрещивающимся прямым, проходящим через отрезки.
- Если да, то кратчайшее расстояние между ними - это кратчайшее расстояние между скрещивающиися прямыми, проходящими через эти отрезки.
- Если нет, то кратчайшее расстояние между ними - это расстояние между какими-то вершинами. Проверяем все варианты - это 2х2=4 варианта: PT11-PT21, PT11-PT22, PT12-PT21, PT12-PT22. Тут PT11 и PT12 - вершины первого отрезка, PT21 и PT22 - вершины второго отрезка.

Для вариантов полилиния с полилинией надо попарно каждые сегменты одной полилинии тестировать с каждым сегментом другой полилинии по вышеприведенному алгоритму для отрезков (слово "отрезок" заменить на слово "сегмент"). Вариантов будет NхM, где N и M - количества сегментов в полилиниях. Чем их больше - тем больше вычислений и дольше работа программы.

Все это справедливо, только для этого случая, когда полилинии состоят только из линейных сегментов.

Метод №2 - итерационный:
Это как раз то, что Дима_ предложил в #2.
Берем одну линию (неважно какого типа - отрезок или полилинию), делим ее на маленькие отрезки, определяем расстояния от центров этих отрезков до второй линии - на это есть стандартные функции vlax-curve-... Оставляем тот отрезок, на котором это расстояние окажется минимальным, делим его на отрезочки поменьше, снова определяем расстояния от центров уже этих отрезков до второй линии, находим отрезок с минимальным расстоянием... и так до тех пор, пока не достигнем какой-то минимальной длины отрезка, например 1e-6.

Здесь, мне кажется, гораздо разумнее делать по 2-му методу.

Последний раз редактировалось Do$, 31.05.2012 в 00:21.
Do$ вне форума вставить имя Обратить внимание модератора на это сообщение  
 
Непрочитано 31.05.2012, 10:24
#5
TararykovDG

Программист-энтузиаст
 
Регистрация: 17.07.2009
Воронеж
Сообщений: 569


Предлагаю такой вариант, из первой вершины первой кривой с помощью vlax-curve-getClosestPointTo находим точку на второй кривой, из этой точки на второй кривой vlax-curve-getClosestPointTo на первую кривую. И так далее, пока точки на кривых не начнут попадать сами в себя, таком образом найдем минимальное расстояние на некотором сегменте. Теперь делаем так для каждой вершины первой кривой (на самом деле можно пропускать все вершины которые попали в последний сегмент) и из набора минимальных расстояний на сегментах берем, минимальное оно и будет минимальным для всей кривой.
NEDIS, попробуй так
Код:
[Выделить все]
 
; Пример вызова:
; (get-min-dist-bw-curve (car (entsel "\nУкажите первую кривую: ")) (car (entsel "\nУкажите вторую кривую: ")))
(defun get-min-dist-bw-curve(curve1 curve2 / )
  (vl-load-com)
  ((lambda(lst_vertex_curve1 lst_vertex_curve2)
     ((lambda(lst_data)
        ((lambda(lst_vertex_curve curve_1 curve_2)
           ((lambda(lst)
              (entmake (list '(0 . "LINE") '(62 . 5) (cons 10 (cadr lst)) (cons 11 (caddr lst))))
              (prompt (strcat "\nМинимальное расстояние между кривыми: " (rtos (car lst))))
              )
             (car (vl-sort (f-rec lst_vertex_curve curve_1 curve_2) '(lambda(rec1 rec2) (< (car rec1) (car rec2)))))
             )
           )
          (car lst_data)
          (cadr lst_data)
          (caddr lst_data)
          )
        )
       (if (< (length lst_vertex_curve1) (length lst_vertex_curve2))
         (list lst_vertex_curve1 curve1 curve2)
         (list lst_vertex_curve2 curve2 curve1)
         )
       )
     )
    (get-vertex curve1)
    (get-vertex curve2)
    )
  (princ)
  ); end get-min-dist-bw-curve

(defun get-min-dist-segment(point cur_1 cur_2 / pt dist)
  (while (> (abs (- (setq dist (distance point (setq pt (vlax-curve-getClosestPointTo cur_2 point))))
                    (distance pt (setq point (vlax-curve-getClosestPointTo cur_1 pt)))
                    )
                 )
            1e-6
            )
    )
  (list dist point pt)
  ); end get-min-dist-segment

(defun f-rec(lst cur_1 cur_2 / )
  (if lst
    (cons (get-min-dist-segment (car lst) cur_1 cur_2)
          (f-rec (cdr lst) cur_1 cur_2)
          )
    )
  ); end f-rec

(defun get-vertex(obj / lst_vertex)
  ((lambda(dxf_code type_obj)
     (cond ((= type_obj "SPLINE")
            (mapcar 'cdr
                    (vl-remove-if-not '(lambda(x) (= (car x) 11)) dxf_code)
                    )
            )
           ((= type_obj "LWPOLYLINE")
            (mapcar 'cdr
                    (vl-remove-if-not '(lambda(x) (= (car x) 10)) dxf_code)
                    )
            )
           ((= type_obj "POLYLINE")
            ((lambda(vertex)
               (while (/= (cdr (assoc 0 (entget vertex))) "SEQEND")
                 (setq lst_vertex (cons (cdr (assoc 10 (entget vertex))) lst_vertex)
                       vertex (entnext vertex)
                       )
                 )
               lst_vertex
               )
              (entnext obj)
              )
            )
           ((= type_obj "LINE")
            (list (cdr (assoc 10 dxf_code)) (cdr (assoc 11 dxf_code)))
            )
           )
     )
    (entget obj)
    (cdr (assoc 0 (entget obj)))
    )
  ); end get-vertex
P.S. NEDIS, вроде бы на Твоем примере отработало нормально, даже в одном месте программа нашла более правильное минимальное расстояние (см. вложения, красным Твои решения, синим то что нашла программа)
Вложения
Тип файла: dwg
DWG 2000
Пример.dwg (877.5 Кб, 2054 просмотров)
__________________
А Вы пробовали выключить и снова включить
TararykovDG вне форума вставить имя Обратить внимание модератора на это сообщение  
 
Непрочитано 31.05.2012, 11:52
#6
Do$

AutoCAD/Civil3D LISP/C#
 
Регистрация: 15.08.2008
Санкт-Петербург
Сообщений: 1,627
Отправить сообщение для Do$ с помощью Skype™


Алгоритм красивый, но надо допиливать.
Во вложении пример, когда неправильный результат выдает.
Вложения
Тип файла: dwg
DWG 2004
Тест.dwg (34.5 Кб, 2045 просмотров)
Do$ вне форума вставить имя Обратить внимание модератора на это сообщение  
 
Непрочитано 31.05.2012, 12:38
#7
TararykovDG

Программист-энтузиаст
 
Регистрация: 17.07.2009
Воронеж
Сообщений: 569


Цитата:
Сообщение от Do$ Посмотреть сообщение
Алгоритм красивый, но надо допиливать.
Во вложении пример, когда неправильный результат выдает.
Ага, интересно, все из-за того, что я из двух кривых за основную выбирал ту, у которой меньше вершин, чтобы уменьшить количество итераций, а на практике надо бы наоборот брать.
первый вариант допила (отличается от исходного кода одним символом, выделено красным)
Код:
[Выделить все]
; Пример вызова:
; (get-min-dist-bw-curve (car (entsel "\nУкажите первую кривую: ")) (car (entsel "\nУкажите вторую кривую: ")))
(defun get-min-dist-bw-curve(curve1 curve2 / )
  (vl-load-com)
  ((lambda(lst_vertex_curve1 lst_vertex_curve2)
     ((lambda(lst_data)
        ((lambda(lst_vertex_curve curve_1 curve_2)
           ((lambda(lst)
              (entmake (list '(0 . "LINE") '(62 . 5) (cons 10 (cadr lst)) (cons 11 (caddr lst))))
              (prompt (strcat "\nМинимальное расстояние между кривыми: " (rtos (car lst))))
              )
             (car (vl-sort (f-rec lst_vertex_curve curve_1 curve_2) '(lambda(rec1 rec2) (< (car rec1) (car rec2)))))
             )
           )
          (car lst_data)
          (cadr lst_data)
          (caddr lst_data)
          )
        )
       (if (> (length lst_vertex_curve1) (length lst_vertex_curve2))
         (list lst_vertex_curve1 curve1 curve2)
         (list lst_vertex_curve2 curve2 curve1)
         )
       )
     )
    (get-vertex curve1)
    (get-vertex curve2)
    )
  (princ)
  ); end get-min-dist-bw-curve

(defun get-min-dist-segment(point cur_1 cur_2 / pt dist)
  (while (> (abs (- (setq dist (distance point (setq pt (vlax-curve-getClosestPointTo cur_2 point))))
                    (distance pt (setq point (vlax-curve-getClosestPointTo cur_1 pt)))
                    )
                 )
            1e-6
            )
    )
  (list dist point pt)
  ); end get-min-dist-segment

(defun f-rec(lst cur_1 cur_2 / )
  (if lst
    (cons (get-min-dist-segment (car lst) cur_1 cur_2)
          (f-rec (cdr lst) cur_1 cur_2)
          )
    )
  ); end f-rec

(defun get-vertex(obj / lst_vertex)
  ((lambda(dxf_code type_obj)
     (cond ((= type_obj "SPLINE")
            (mapcar 'cdr
                    (vl-remove-if-not '(lambda(x) (= (car x) 11)) dxf_code)
                    )
            )
           ((= type_obj "LWPOLYLINE")
            (mapcar 'cdr
                    (vl-remove-if-not '(lambda(x) (= (car x) 10)) dxf_code)
                    )
            )
           ((= type_obj "POLYLINE")
            ((lambda(vertex)
               (while (/= (cdr (assoc 0 (entget vertex))) "SEQEND")
                 (setq lst_vertex (cons (cdr (assoc 10 (entget vertex))) lst_vertex)
                       vertex (entnext vertex)
                       )
                 )
               lst_vertex
               )
              (entnext obj)
              )
            )
           ((= type_obj "LINE")
            (list (cdr (assoc 10 dxf_code)) (cdr (assoc 11 dxf_code)))
            )
           )
     )
    (entget obj)
    (cdr (assoc 0 (entget obj)))
    )
  ); end get-vertex
P.S. Да, сейчас вот догадался, такой вариант допила тоже будет работать далеко не всегда, будем думать

P.P.S. Второй вариант допила, вроде как работает
Код:
[Выделить все]
 
; Пример вызова:
; (get-min-dist-bw-curve (car (entsel "\nУкажите первую кривую: ")) (car (entsel "\nУкажите вторую кривую: ")))
(defun get-min-dist-bw-curve(curve1 curve2 / )
  (vl-load-com)
  ((lambda(lst_vertex_curve1 lst_vertex_curve2)
     ((lambda(lst)
        (entmake (list '(0 . "LINE") '(62 . 5) (cons 10 (cadr lst)) (cons 11 (caddr lst))))
        (prompt (strcat "\nМинимальное расстояние между кривыми: " (rtos (car lst))))
        )
       (car (vl-sort (append (f-rec lst_vertex_curve1 curve1 curve2)
                             (f-rec lst_vertex_curve2 curve2 curve1)
                             )
                     '(lambda(rec1 rec2) (< (car rec1) (car rec2)))
                     )
            )
       )
     )
    (get-vertex curve1)
    (get-vertex curve2)
    )
  (princ)
  ); end get-min-dist-bw-curve

(defun get-min-dist-segment(point cur_1 cur_2 / pt dist)
  (while (> (abs (- (setq dist (distance point (setq pt (vlax-curve-getClosestPointTo cur_2 point))))
                    (distance pt (setq point (vlax-curve-getClosestPointTo cur_1 pt)))
                    )
                 )
            1e-6
            )
    )
  (list dist point pt)
  ); end get-min-dist-segment

(defun f-rec(lst cur_1 cur_2 / )
  (if lst
    (cons (get-min-dist-segment (car lst) cur_1 cur_2)
          (f-rec (cdr lst) cur_1 cur_2)
          )
    )
  ); end f-rec

(defun get-vertex(obj / lst_vertex)
  ((lambda(dxf_code type_obj)
     (cond ((= type_obj "SPLINE")
            (mapcar 'cdr
                    (vl-remove-if-not '(lambda(x) (= (car x) 11)) dxf_code)
                    )
            )
           ((= type_obj "LWPOLYLINE")
            (mapcar 'cdr
                    (vl-remove-if-not '(lambda(x) (= (car x) 10)) dxf_code)
                    )
            )
           ((= type_obj "POLYLINE")
            ((lambda(vertex)
               (while (/= (cdr (assoc 0 (entget vertex))) "SEQEND")
                 (setq lst_vertex (cons (cdr (assoc 10 (entget vertex))) lst_vertex)
                       vertex (entnext vertex)
                       )
                 )
               lst_vertex
               )
              (entnext obj)
              )
            )
           ((= type_obj "LINE")
            (list (cdr (assoc 10 dxf_code)) (cdr (assoc 11 dxf_code)))
            )
           )
     )
    (entget obj)
    (cdr (assoc 0 (entget obj)))
    )
  ); end get-vertex
__________________
А Вы пробовали выключить и снова включить

Последний раз редактировалось TararykovDG, 31.05.2012 в 13:05.
TararykovDG вне форума вставить имя Обратить внимание модератора на это сообщение  
 
Непрочитано 31.05.2012, 13:10
#8
Do$

AutoCAD/Civil3D LISP/C#
 
Регистрация: 15.08.2008
Санкт-Петербург
Сообщений: 1,627
Отправить сообщение для Do$ с помощью Skype™


Цитата:
Сообщение от TararykovDG Посмотреть сообщение
Ага, интересно, все из-за того, что я из двух кривых за основную выбирал ту, у которой меньше вершин, чтобы уменьшить количество итераций, а на практике надо бы наоборот брать.
А что если обе полилинии так обрабатывать? Мне кажется, тогда все ОК будет.
Пы.Сы. Кажется, так и сделано уже
Do$ вне форума вставить имя Обратить внимание модератора на это сообщение  
 
Непрочитано 31.05.2012, 13:17
#9
Vov.Ka


 
Регистрация: 21.07.2008
Луцьк
Сообщений: 133


Цитата:
Сообщение от Кулик Алексей aka kpblc Посмотреть сообщение
Вроде бы на theswamp.org были какие-то лиспы
http://www.theswamp.org/index.php?topic=23170.0
Vov.Ka вне форума вставить имя Обратить внимание модератора на это сообщение  
 
Автор темы   Непрочитано 02.06.2012, 16:40
#10
NEDIS

Инженер СКС
 
Регистрация: 21.08.2009
г. Домодедово МО
Сообщений: 72


уууух спасибо за помощь ... я только с поездки вернулся, буду разбираться
NEDIS вне форума вставить имя Обратить внимание модератора на это сообщение  
 
Непрочитано 28.07.2017, 12:28
#11
db-78


 
Регистрация: 24.10.2016
Сообщений: 3


Прошу помочь с лиспом.

Есть три отрезка (скважин), нужно найти точку на центральном отрезке на расстоянии 1,3м от двух соседних. Рисунок прилагаю.
Миниатюры
Нажмите на изображение для увеличения
Название: веер.png
Просмотров: 33
Размер:	24.0 Кб
ID:	191620  
db-78 вне форума вставить имя Обратить внимание модератора на это сообщение  
 
Непрочитано 28.07.2017, 12:47
#12
Enik

ГИП
 
Регистрация: 07.06.2015
Сообщений: 798


Цитата:
Сообщение от db-78 Посмотреть сообщение
нужно найти точку на центральном отрезке на расстоянии 1,3м от двух соседних.
А отрезок 2 - это точно биссектриса? В противном случае такая точка не может существовать.
Enik вне форума вставить имя Обратить внимание модератора на это сообщение  
 
Непрочитано 28.07.2017, 13:34
#13
db-78


 
Регистрация: 24.10.2016
Сообщений: 3


нет не биссектриса. Это скважины и расчет заряда а 1,3м это линия наименьшего сопротивления. Рисовать недозаряд в каждой скважине накладно и отнимает много времени.
db-78 вне форума вставить имя Обратить внимание модератора на это сообщение  
 
Непрочитано 28.07.2017, 13:43
1 | #14
VVA

Инженер LISP
 
Регистрация: 11.05.2005
Минск
Сообщений: 6,543
Отправить сообщение для VVA с помощью ICQ Отправить сообщение для VVA с помощью Skype™


db-78, Команда КРУГ, опция ККР (касательная, касательная радиус) не подойдет?. Касательный - 2 крайних отрезка, радиус 1.3/2=0.65 м
__________________
Как использовать код на Лиспе читаем здесь
VVA вне форума вставить имя Обратить внимание модератора на это сообщение  
 
Непрочитано 01.08.2017, 09:11
#15
db-78


 
Регистрация: 24.10.2016
Сообщений: 3


Цитата:
Команда КРУГ
Спасибо за подсказку! Команда подходит, вынесу кнопки и буду так работать. А не поможете с лиспом, чтоб все автоматически было?
db-78 вне форума вставить имя Обратить внимание модератора на это сообщение  
 
Непрочитано 02.08.2017, 13:48
1 | #16
VVA

Инженер LISP
 
Регистрация: 11.05.2005
Минск
Сообщений: 6,543
Отправить сообщение для VVA с помощью ICQ Отправить сообщение для VVA с помощью Skype™


Там лиспа всего 1 строчка, и все это можно сделать макросом на кнопке
Код:
[Выделить все]
(vl-load-com)(vl-cmdf "_.CIRCLE" "_TTR" pause pause 1.3)
Макрос на кнопку
Цитата:
^C^C_.CIRCLE;_TTR;\\1.3
1.3 - требуемый отступ
__________________
Как использовать код на Лиспе читаем здесь
VVA вне форума вставить имя Обратить внимание модератора на это сообщение  
Ответ
Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > Поиск минимального расстояния между линейными примитивами

 VetCAD++
Размещение рекламы
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Расстояния между компенсаторами тепловых сетей proekt_mep Отопление 10 29.05.2012 14:17
Автоматический поиск заданного расстояния между двумя линиями Shaft Программирование 18 08.07.2010 13:53
Расчет расстояния между температурно-усадочными швами в ж/б конструкциях Анастасия Филимонова Железобетонные конструкции 7 11.02.2010 13:02
Масштабирование нескольких объектов без изменения расстояния между ними...Как!?!? Botan AutoCAD 1 23.07.2009 17:35
Расстояния между температурно-усадочными швами по нормам novichOK Конструкции зданий и сооружений 4 22.05.2009 17:39

|| Главная || Каталог САПР || Тендеры || Публикации || Объявления || Биржа труда || Download || Галерея ||
|| Библиотека || Кунсткамера || Каталог предприятий || Контакты || Файлообменник || Блоги ||