Exception occurred: 0xC0000005 (Access Violation): alloc, expand или что делать?

Автор Тема: Exception occurred: 0xC0000005 (Access Violation): alloc, expand или что делать?  (Прочитано 5614 раз)

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

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

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

  • ADN OPEN
  • **
  • Сообщений: 57
  • Карма: 1
На чертеже имеется 3000 отрезков (может быть и больше). Нужно найти все точки их пересечений.
Использую примерно такой код с немного преобразованными функциями от Lee Mac (inters вместо intersectwith). Для 3000 отрезков получается около 5 миллионов запусков inters, в результате всё висит, пока не появляется ошибка
; ошибка: Возникло исключение: 0xC0000005 (Нарушение доступа)

Код - Auto/Visual Lisp [Выбрать]
  1. (setq ss nil ss (ssget "_X" '((0 . "LINE")))); набор всех отрезков на чертеже
  2. (if (not ss) (setq ss (ssadd)))
  3. (setq all_lines_list (vl-remove-if-not (function (lambda (x) (= (type x) 'ename))) (mapcar 'cadr (ssnamex ss)))); список всех отрезков
  4. (setq ss nil vla_line_list nil)
  5. (foreach item all_lines_list (setq vla_line_list (append vla_line_list (list (vlax-ename->vla-object item))))); список всех vla-объектов-отрезков
  6. (setq all_inters_points nil all_inters_points (LM:intersectionsinobjlist vla_line_list)); поиск всех точек пересечения
  7.  
  8. (defun LM:intersectionsinobjlist (lst / ob1 rtn )
  9.     (while (setq ob1 (car lst))
  10.         (foreach ob2 (setq lst (cdr lst))
  11.             (setq rtn (cons (LM:intersections ob1 ob2) rtn))
  12.         )
  13.     )
  14.     (apply 'append (reverse rtn))
  15. );defun
  16.  
  17. (defun LM:intersections (ob1 ob2 / lst rtn )
  18.     (setq lst (inters (vlax-curve-getStartPoint ob1) (vlax-curve-getEndPoint ob1) (vlax-curve-getStartPoint ob2) (vlax-curve-getEndPoint ob2)))
  19.     (repeat (/ (length lst) 3)
  20.         (setq rtn (cons (list (car lst) (cadr lst) (caddr lst)) rtn) lst (cdddr lst))
  21.     )
  22.     (reverse rtn)
  23. );defun

На одном из форумов видел сообщение от Александра Ривилиса об использовании функции expand. Не очень понял, за что именно отвечает expand и alloc (и как их подбирать), но значения вроде 1000 для alloc и 10000 для expand проблему не решили. Что тут можно ещё сделать?

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Что тут можно ещё сделать?
Радикально изменить алгоритм.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • **
  • Сообщений: 57
  • Карма: 1
При поиске точек пересечения всех отрезков друг с другом в любом случае потребуется перебрать все комбинации отрезков. Сам код несложный, но объём операций огромный. Как его упростить, в какую сторону "копать"?

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
1. Не нужны здесь vla-/vlax-методы. Для отрезков достаточно получать dxf-группы 10 и 11
2. Что это за заумное выражение:
Код - Auto/Visual Lisp [Выбрать]
  1.     (repeat (/ (length lst) 3)
  2.         (setq rtn (cons (list (car lst) (cadr lst) (caddr lst)) rtn) lst (cdddr lst))
  3.     )
???
3. Можно перед проверкой на пересечение отрезков проверять факт пересечения BoundingBox обоих отрезков. Если они не пересекаются, то и отрезки не могут пересекаться.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • **
  • Сообщений: 57
  • Карма: 1
1. Изменил vla- на (cdr (assoc (entget...
2. Заумное выражение сделано для полилиний со множественными пересечениями, тут действительно лишнее.
После этих двух исправлений ошибка исчезла, хотя время ожидания составляет около 5 минут.
А как BoundingBox может помочь? Ведь это дополнительный поиск пересечений, а сейчас один только inters?

Оффлайн Владимир Шу

  • ADN Club
  • *****
  • Сообщений: 611
  • Карма: 155
    • ПГСу Бложик
А как BoundingBox может помочь? Ведь это дополнительный поиск пересечений, а сейчас один только inters?

Попробуйте разделить весь массив линий на несколько зон и потом искать пересечения только в линиях внутри зоны, а вообще 
тут на форуме обсуждалось использование R-tree для быстрого поиска.

Отмечено как Решение Macondo 31-08-2017, 21:31:04

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
А как BoundingBox может помочь? Ведь это дополнительный поиск пересечений, а сейчас один только inters?
Пересечении в данном случае это проверки пересечения диапазонов [X1min,X1max] с [X2min,X2max] и [Y1min,Y1max] с [Y2min,Y2max]. Если пересечений диапазонов нет, то нечего и проверять пересечение самих отрезков при помощи inters.
Кроме того, я подозреваю что ты вызвал каждый раз в цикле (entget) для каждого из отрезков. А нужно один раз пройтись по всем отрезкам и создать список вида '((P1начала P1конца) ... (PNначала PNконца)) и тогда находить пересечения будет намного проще и быстрее.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение