воскресенье, 8 августа 2010 г.

Лучи и продолженные линии

Вот потихоньку я и добрался до того момента когда приходится применять знания гугла геометрии и математики, ну и немного интуиции.
Первое что я поборол - это отрисовка лучей и продолженных линий. их основная загвоздка в том что надо находить точки на грани виджета, куда надо направлять линию. Луч я рисую так:

(defun parser-ray (cd w h)
  (set-source-rgb 0 0 1)
  (set-line-width 1)
  (move-to (* *scroll-units* (getf cd :x1))
          (* *scroll-units* (getf cd :y1)))
  (line-to (* (/ (getf cd :x1) *scroll-units*
          (let ((x1 (getf cd :x1))
               (y1 (getf cd :y1))
               (x2 (getf cd :x2))
               (y2 (getf cd :y2)))
(+ 
(* (- w y1) 
              (/ (- x2 x1) 
                 (- y2 y1)))
x1)))
         (* (/ (getf cd :y1) *scroll-units*
            (let ((x1 (getf cd :x1))
                 (y1 (getf cd :y1))
                 (x2 (getf cd :x2))
                 (y2 (getf cd :y2)))
(* (/ (- y2 y1)
                  (- x2 x1))
               (- h x1)))))
  (stroke))
Вроде нигде не наврал, но есть проблема - если зуммировать изображение до размеров точки, то луч и прод.линия начинают люто-бешено прыгать по экрану. Как мне помнится такое я наблюдал в компасе, qcad и еще где то, так что не особо обеспокоен этим фактом. ЕМНИП в автокаде есть на это дело границы зуммирования. Чуть позже разберусь с этим.
А пока вот рабочий скрин:

10 коммент.:

  1. Только что обнаружил косяк - при изменении геометрии окна, у лучей и прод.линий меняются углы. придется снова распутывать клубок и смотреть откуда грабли

    ОтветитьУдалить
  2. Не нравятся мне эти формулы с делениями. Помню, что в задачах по выч.геометрии старались избегать делений, а пользоваться только умножениями.

    Вопрос номер 0: а числа в double-float или single-float? У single-float маленькая точность, что-то около 7-8 значащих десятичных знаков.

    ОтветитьУдалить
  3. Что либо считать в момент рисования - ИМХО не правильно. считать нужно отдельно, рисовать отдельно - расход памяти, но без этого никакой производительности небудет.
    При делении обязательно проверки на 0 и соответственно расчет вертикальных и горизонтальных прямых разными способами.

    В атокаде нет ограничений зуммирования, вернее есть, но они снимаются регенерацией чертежа.

    ОтветитьУдалить
  4. формулы кривые, это да. Надо поднимать школьную программу по геометрии. числа вроде в double-float. Кстати, а как это можно деление заменить умножением?

    ОтветитьУдалить
  5. @Andrey в автокаде после регенерации по хитрому меняются координаты экрана. По этому артефактов не вылазит.

    ОтветитьУдалить
  6. >>в автокаде после регенерации по хитрому меняются координаты экрана??

    в смысле?

    ОтветитьУдалить
  7. точно не помню как вся эта кухня работает, но суперзум после регенерации не вызывает артефактов. по моему там перестают обращать внимание на элементы вне видимой области

    ОтветитьУдалить
  8. >Кстати, а как это можно деление заменить умножением?

    Пользоваться теми формулами/уравнениями, где деление не нужно. Например, вместо уравнения прямой y=kx+b использовать уравнение ax+by+c=0

    Еще, раз уж используется лисп, то для произвольного зума имеет смысл вычисления делать в точной рациональной арифметике, а потом переводить в плавающую точку.

    ОтветитьУдалить
  9. ax+by+c=0 и y=kx+b это одна и таже форма задание прямой. удобней использовать p=dx*t+dy*t, но от деления всеравно избавиться не получится - в этом случае на ноль не придется делить для вертикальных\горизонтальных прямых.

    >>имеет смысл вычисления делать в точной рациональной арифметике

    У вас погрешность не от плавающей точки, а от неправильной обработки изменения размеров окна.

    ОтветитьУдалить
  10. описался - совместил векторную и невекторную формы и забыл постоянную чисть)), имел ввиду
    p=p1+(p2-p1)*t

    ОтветитьУдалить