Тема: Создание пикетажной ведомости

Есть полиния трассы.
Есть набор точек лежащих вдоль (и не совсем вдоль трассы)
Есть начальный пикет.
Требуется определить пикетаж каждой точки и ее расстояние от трассы.
Наброски моего видения на "псевдоязыке":
i=0
начало:
rast=0
Берем вершину полилинии с номером i
Ставим пск в эту точку, x направляем к вершине i+1, y "вверх" (всегда в одну сторону от полилинии)
Все точки, x которых меньше длины отрезка полилинии i - i+1 записываем в ведомость. Пикетаж у них равен rast+x, расстояние от трассы = y.
rast=rast+длина отрезка полилинии i - i+1
goto начало
Проблемы:
1) точка может определяться не один раз, если трасса изгибается и перпендикуляр неоднозначен, то есть может опускаться на разные части трассы
для решения наверное надо вводить коридор отбора (то есть если y трассы больше чем заданная величина коридора, то точку не определяем).
И(/или?) надо выбирать минимальное расстояние до трассы из всех возможных перпендикуляров.
2) точка может не иметь перпендикуляра на трассе. Такое происходит, если точка лежит в стороне от вершины угла на тупой его части. Перпендикуляр здесь попадает только на продолжение отрезков полилинии. В этом случае требуется присваивать такой точке пикетаж вершины угла. НО! перпендикуляр к этой точке может и существовать, но быть (не)значительно длиннее, чем расстояние до вершины угла.
Наверное просто надо еще и определять для каждой точки расстояние до ближайшей вершины дополнительно к длинне перпендикуляра и выбирать минимальное? И не представляю, как обнаруживать такие (не имеющие перпендикуляра) точки
Может кто чего поможет?
В принципе, можно и на vba, но lisp нравится больше.
Ведомость не важно в каком виде, это не проблема.
Заранее благодарю!

Re: Создание пикетажной ведомости

Вот моя программа, конечно не без изъянов.
Писалась под отвод земель под автодорогу и железку.
Функция polosa выполняет нумерацию вершин полилинии, изображающую полосу отвода и в текстовом окне выводит ведомость: номер точки, пикет, ширина полосы от трассы.
Вторая функция polosa_coord выдает ведомость координат.

; определение пикетажного значения
; автор: Иванков Алексей, ЗАО "Востсибтранспроект"
; Иркутск, 2007
(defun piket (len start_pk start_plus / pk plus dist1)
  (setq dist1 (+ (* start_pk 100) start_plus len))
  (setq dist1 (atoi (rtos dist1 2 0)))
  (setq pk (fix (/ dist1 100)))
  (setq plus (rtos (- dist1 (* pk 100)) 2 0))
  (strcat "ПК" (rtos pk 2 0) "+" plus)
)
(defun c:polosa (/         trassa vla_trassa    start_pk start_plus
        dist     plus pk   s_pk   shirina  alist
        a        i  osm  prev_pk  txt    prev_a
       )
  (command "cmdecho" 0)
  (command "dimzin" 4)
  (setq trassa (car (entsel "\nВыделите трассу: ")))
  (setq vla_trassa (vlax-ename->vla-object trassa))
  (setq start_pk (getint "\nПикет в начале трассы: "))
  (setq start_plus (getreal "\nПлюс в начале трассы: "))
  (setq i (getint "\nНачальный номер точки: "))
  (setq alist (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= 10 (car x))) (entget (car (entsel "\nВыделите полосу отвода: "))))))
  (setq prev_pk nil)      ; определение ширины полосы отвода и пикетажных значений
  (foreach a alist
    (progn
      (setq dist (vlax-curve-getDistAtPoint vla_trassa (vlax-curve-getClosestPointTo vla_trassa a)))
      (setq shirina (+ 1.0 (fix (distance a (vlax-curve-getClosestPointTo vla_trassa a)))))
      (if (equal dist prev_pk 1)
  (setq txt (strcat " " (rtos i 2 0) " " (rtos shirina 2 0)))
  (setq txt (strcat "\n" (piket dist start_pk start_plus)  " "  (rtos i 2 0) " " (rtos (fix (+ shirina 0.99)) 2 0)))
      ) ; if
      (prompt txt)
      (setq osm (getvar "osmode"))
      (setvar "OSMODE" 0)
      (command "_text" "_j" "mc" (trans (polar a (/ pi 2) 3) 0 1) "" "" (strcat "н"(rtos i 2 0)))
      (command "_text" "_j" "mc" (trans (polar a (/ (- pi) 2) 3) 0 1) "" "" (rtos (fix (+ shirina 0.99)) 2 0))
      (command "_circle" (trans a 0 1) 0.75)
      (command "_hatch" "s" "l" "")
      (setvar "OSMODE" osm)
      (setq i (+ 1 i) prev_pk dist)
    ); progn
  ); foreach
  (princ)
)
(defun c:polosa_coord(/ alist a txt i flag prev_a ang dist)
  (command "angbase" 0)
  (command "angdir" 0)
  (setq alist (mapcar 'cdr (vl-remove-if-not '(lambda (x) (= 10 (car x))) (entget (car (entsel "\nВыделите полосу отвода: "))))))
  (setq i (atoi (vl-string-left-trim "нН" (cdr (assoc 1 (entget (car (entsel "\nВыделите наименование первой точки полосы отвода: "))))))))
  (setq flag nil)
  (foreach a alist
    (setq txt (strcat "\n" "н" (rtos i 2 0) " " (rtos (cadr (trans a 0 1)) 2 2) " " (rtos (car (trans a 0 1)) 2 2)))
    (if (= flag nil)
      (setq flag t)
      (progn
  (setq ang (- (* 2.5 pi) (angle (trans prev_a 0 1) (trans a 0 1))))
  (if (>= ang (* 2 pi)) (setq ang (- ang (* 2 pi))))
  (setq dist (distance prev_a a))
  (setq txt (strcat txt " " (angtos ang 1) " " (rtos dist 2 2)))
      )
    )
    (prompt txt)
    (setq i (+ 1 i) prev_a a)
  ); foreach
  (princ)
)

Re: Создание пикетажной ведомости

Добрый день!
Очень нужная программа, сэкономит много времени! Но у меня после определения ширины полосы отвода в первой точке далее выдает ошибку:
"Неправильное ключевое слово.
; ошибка: Функция отменена"

Подскажите в чем причина?
Заранее спасибо!