Привязка должна работать к одной наиближайшей точке. К тому же точки, не попадающие в некоторый диапазон, не должны вообще рассматриваться. То есть должна быть некая область действия привязки. Пусть она будет равна 10.
(defparameter *osnap-area-delta* 10)
Еще нам понадобятся пара глобальных переменных
(defvar *x* nil)
(defvar *y* nil)
При вводе объектов нужно будет ввести координаты точки. Их мы получим из привязки либо, если не найдется точки входящей в область привязок, непосредственно от курсора. Нужен еще вариант ввода с терминала, но это другая песня. А раз уж получение координат едино для любого примитива, то стоит оформить это дело отдельной функцией
(defun get-point-coordinates ()
(if (<= (get-delta) *osnap-area-delta*)
(get-snap-coordinates)
(get-native-coordinates)))
Все просто - примитивное сравнивание на пригодность. По клику мышкой мы получим либо то либо то. Ошибиться пока негде! Но сразу видно что чего то не хватает, а именно самого мяса этих привязок! Значит - поехали дальше!
Во первых, где мы возьмем сами координаты курсора? А в обработчике motion-notify-event - вот где!
(gobject:connect-signal w "motion-notify-event" (lambda (widget event)
(declare (ignore widget))
(setf x2 (event-motion-x event)
y2 (event-motion-y event))
(widget-queue-draw window)))
Пока мы возим мышкой по области рисования, обработчик будет сохранять текущие координаты в x2 и y2. Эти самые значения и будут переданы на ввод, если не найдется подходящая точка для привязки. Но для нахождения точки привязки нужно выбрать подходящую из нескольких доступных. Координаты для вычисления дистанции мы берем непосредственно из :x1 :y1 или :x2 :y2. При этом вычисляться должны дистанции отдельно и для середины отрезка и для конца отрезка, да и вообще все!
Вы уже чувствуете как вырастает нагрузка на процессор? Посмотрим как окажется на деле!
Если расчет привязок достаточно геморройная задача, то получение координат непосредственно реализовать не сложно:
(setf *x* x2
*y* y2)
Для работы с множеством различных привязок мне потребуется обобщенная функция:
(defgeneric snap (osnap))
Для центров, середин, окончаний и точек касаний нужно определить каждому свой метод. При этом метод должен работать при условии если в переменной *osnap-..*, соответствующей ему, есть t
Сами привязки опишу чуть позже в этом же посте!

можно пару вопросов?
ОтветитьУдалить1 - cad будет 2д или 3д?
2 - это какие привязки? те которые при черчении или при выделении(синие ручки в автокаде)?
Пока 2d не осилю до приемлемого качества, 3d даже не затрону. Хотя в движке место для этого зарезервировано. Привязки это когда примагничиваешься к координатам уже введенных точек. В автокаде они подсвечиваются квадратиками и треугольниками
ОтветитьУдалитьесли 3d планируется - имхо лучше делать сразу с учетом 3d. т.е. с учетом z и не попадание в квадрат шириной osnap-area-delta, а в пирамиду с основанием osnap-area-delta.
ОтветитьУдалитьВаш подход предполагает работу в экранных координатах, т.е. все примитивы придется проецировать на экран и хранить "ненужные" координаты. Пока на чертеже линии и кружочки - всё вроде нормально, но с появлением векторных шрифтов - будет заметно тормозить и расходовать память.
Перед привязками имеет смысл сделать выбор примитивов мышкой, чтобы иметь небольшой список примитивов под мышкой и на привязку обрабатывать только их
а почему именно пирамиду? я предполагал что это будет куб. Выбирать примитивы для привязки будет не совсем удобно - многовато будет мелкой ручной работы
ОтветитьУдалитьс перспективой - усеченная пирамида, без - параллепипед. Примитивы под мышкой нужны для привязки "пересечение" - искать пересечение только нескольуих примитивов, а не всех видимых
ОтветитьУдалить