Тема: Макрос на кнопку "Равноудаленная линия"
Можно ли и как написать макрос на кнопку для построения равноудаленной линии от двух других?
Информационный портал для профессионалов в области САПР
Вы не вошли. Пожалуйста, войдите или зарегистрируйтесь.
Форумы CADUser → Программирование → Настройка меню и DIESEL → Макрос на кнопку "Равноудаленная линия"
Чтобы отправить ответ, вы должны войти или зарегистрироваться
Можно ли и как написать макрос на кнопку для построения равноудаленной линии от двух других?
Опять же программа (сырая заготовка):
(defun C:M_LINE ( / ob1 ob2 line1 line2 p11 p12 p21 p22) (setvar "CMDECHO" 0) (setq ob1 (entsel "\n Выберите первый отрезок: ")) (setq ob2 (entsel "\n Выберите второй отрезок: ")) (setq line1 (entget (car ob1))) (setq line2 (entget (car ob2))) (setq p11 (cdr (assoc 10 line1))) (setq p12 (cdr (assoc 11 line1))) (setq p21 (cdr (assoc 10 line2))) (setq p22 (cdr (assoc 11 line2))) (command "_LINE" "_m2p" p11 p21 "_m2p" p12 p22 "") (princ) )
Результат может получится обескураживающим, если существующие отрезки были нарисованы "навстречу друг другу".
И уж совсем примитивный вариант программы:
(defun C:M_LINE ( / p11 p12 p21 p22) (setvar "CMDECHO" 0) (setq p11 (getpoint "\n Начало первой линии: ")) (setq p21 (getpoint "\n Начало второй линии: ")) (setq p12 (getpoint "\n Конец первой линии: ")) (setq p22 (getpoint "\n Конец второй линии: ")) (command "_LINE" "_m2p" p11 p21 "_m2p" p12 p22 "") (princ) )
> Владимир Громов
Спасибо. Сейчас буду тестировать:)
> Владимир Громов
...не...не тот алгоритм...я сейчас пороюсь...писал колысь такой макрос
, правда, на другом языке и для другого CAD'a...
> Владимир Громов
...вот...думаю поможет...очень просто...
// Copyright (c) ++++++++++++++ // Author: ++++++++++++++++++++ // prototype-Example +++++++++++++++ HANDLE hLine,hEntity; XY xyStartA, xyEndA,xyStartB, xyEndB,xyStart, xyEnd; hEntity = GetEntity("select 1 line", "line"); if (hEntity) { GetGeometry(hEntity , &xyStartA, &xyEndA); Print("Line=", xyStartA, xyEndA, "\n"); } hEntity = GetEntity("select 2 line", "line"); if (hEntity) { GetGeometry(hEntity , &xyStartB, &xyEndB); Print("Line=", xyStartB, xyEndB, "\n"); } SetData("PenColor", 4); SetData("PenStyle", 6); SetData("PenWidth",0); { xyStart.x=(xyStartA.x+xyStartB.x)/2; xyStart.y=(xyStartA.y+xyStartB.y)/2; xyEnd.x=(xyEndA.x+xyEndB.x)/2; xyEnd.y=(xyEndA.y+xyEndB.y)/2; //SetGeometry(hEntity, xyStart, xyEnd); hEntity = AddEntity("line", xyStart,xyEnd); Execute("menu", "SetColor",4); Execute("menu", "SetStyle", 3); Execute("menu", "SetWidth", 0); } //AddEntity("line", xyStart.x,xyStart.y,xyStart.x,xyStart.y); Exit(%ok, "Done adding centrline."); // [EndOfMacro]
> Forma
Ну, тогда уж пиши подробнее, что ты хошь...
Вот, увидел твой код, это же на C, это я не очень-то.
А словами разве нельзя описать смысл?
Хотя похоже на отрисовку отрезка между серединами крайних точек существующих отрезков.
Так и у меня тоже самое делаеся, только цвет, стиль (?), ширина (вес?) приняты по умолчанию.
А что алгоритм? Алгоритмы разные бывают. Важен результат. Так что надо получить?
> Владимир Громов
...да писать дольше чем показать...короче...угол и бисектрисса...
только цвет, стиль (?), ширина (вес?)
....это лишнее...не надо...
Так и надо было написать: "Как построить биссектрису угла?" Но эта задача легко решается с помощью привязки "_m2p" (середина между двумя точками), которая вызывается с помощью курсорного меню по Shift+правая кнопка мыши (AutoCAD 2005).
> Владимир Громов
...да это понятно...кликов то сколько...хотел мало- мало автоматизировать...
Господи, есть же предел простоты, когда автоматизация теряет смысл, да и что за интерес кнопки плодить? В программе можно обойтись двумя кликами при условии, что отрезки выходят из одной точки, только повторюсь, что остается неопределенность в положении начальной и конечной точек существующих отрезков.
> Владимир Громов
Ну начало и конец существующих отрезков можно пронализировать. Как вариант (не программа, а только алгоритм):
(setq e1 (entget (car (entsel "\nПервый отрезок: ")))) (setq e2 (entget (car (entsel "\nВторой отрезок: ")))) (setq p11 (cdr (assoc 10 e1)) p12 (cdr (assoc 11 e1)) p21 (cdr (assoc 10 e2)) p22 (cdr (assoc 11 e2))) (if (> (+ (distance p11 p21) (distance p12 p22)) (+ (distance p11 p22) (distance p12 p21))) (progn ; Меняем местами начало и конец второго отрезка (setq tmp (list p21 p22) p21 (cadr tmp) p22 (car tmp)) )) ;; Находим середины между концами отрезков (setq p1 (mapcar '* '(0.5 0.5 0.5) (mapcar '+ p11 p21))) (setq p2 (mapcar '* '(0.5 0.5 0.5) (mapcar '+ p12 p22))) (command "_.LINE" "_none" (trans p1 0 1) "_none" (trans p2 0 1) "")
А вот откуда начинать и где кончать новый отрезок в общем случае - вопрос?
Сообщение Александр Ривилиса появилось раньше.
Ну, вот пусть будет такая программа:
(defun C:M_LINE ( / ob1 ob2 line1 line2 p11 p12 p21 p22) (setvar "CMDECHO" 0) (setq ob1 (entsel "\n Выберите первый отрезок: ")) (redraw (car ob1) 3) (setq ob2 (entsel "\n Выберите второй отрезок: ")) (redraw (car ob2) 3) (setq line1 (entget (car ob1))) (setq line2 (entget (car ob2))) (setq p11 (cdr (assoc 10 line1))) (setq p12 (cdr (assoc 11 line1))) (setq p21 (cdr (assoc 10 line2))) (setq p22 (cdr (assoc 11 line2))) (command "_LINE" p11 "_m2p" p12 p22 "") (redraw (car ob1) 4) (redraw (car ob2) 4) (princ) )
Только необходимо, чтобы существующие отрезки ВЫХОДИЛИ из одной точки.
А больше мне думать неохота. Может, Александр Ривилис доделает, как всегда, а?
А вот откуда начинать и где кончать новый отрезок в общем случае - вопрос?
Не принципиально. Реально, из моего опыта, будет чуть длинее или короче. Все равно с ней дальше работать.
чтобы существующие отрезки ВЫХОДИЛИ из одной точки
Так не пойдет. Ограничение суровое.
> Владимир Громов
Ладно. Но не доделаю, а переделаю. Но имя программы сохраню Ваше...
Выходить отрезки из одной точки не обязаны... Получается скорее не биссектриса, а медиана...
(defun C:M_LINE ( / en1 en2 e1 e2 p1 p2 p11 p12 p21 p22 tmp) (setvar "CMDECHO" 0) (setq en1 (car (entsel "\nВыберите первый отрезок: "))) (if en1 (redraw en1 3)) (setq en2 (car (entsel "\nВыберите второй отрезок: "))) (if en2 (redraw en2 3)) (if (and en1 en2 (setq e1 (entget en1)) (setq e2 (entget en2)) (= "LINE" (cdr (assoc 0 e1))) (= "LINE" (cdr (assoc 0 e2)))) (progn (setq p11 (cdr (assoc 10 e1)) p12 (cdr (assoc 11 e1)) p21 (cdr (assoc 10 e2)) p22 (cdr (assoc 11 e2))) (if (> (+ (distance p11 p21) (distance p12 p22)) (+ (distance p11 p22) (distance p12 p21))) (progn ; Меняем местами начало и конец второго отрезка (setq tmp (list p21 p22) p21 (cadr tmp) p22 (car tmp)) ;; Находим середины между концами отрезков )) (setq p1 (mapcar '* '(0.5 0.5 0.5) (mapcar '+ p11 p21))) (setq p2 (mapcar '* '(0.5 0.5 0.5) (mapcar '+ p12 p22))) (command "_.LINE" "_none" (trans p1 0 1) "_none" (trans p2 0 1) "") ) (progn (princ "\nЧто-то не выбрано, или выбрано что-то не то!") ) ) (if en1 (redraw en1 4)) (if en2 (redraw en2 4)) (princ) )
> Александр Ривилис
;; Находим середины между концами отрезков
Это явно не то. Углы разные. Это медиана. Бисектрисса должна быть. А, как? Буду разбираться. Для начала в своем
же макросе. Может и у меня было также. Хотя, я еще в трезвой памяти. Не помню "нестандартных" ситуаций.
> Forma
Конечно же в Ваше алгоритме тоже медианы... В частном случае может быть и биссектриса...
> Forma
Поковыряйтесь еще в своем алгоритме - мой практически один в один Ваш, кроме дополнительной смены начала и конца отрезка. До утра времени масса. А пока спокойной ночи!
Я про это не сразу и сообразил, исходные отрезки были практически одинаковы. Да и не медиана это, потому что нет треугольника. Надо все начинать сначала, чтоб мне застрелиться.
> Александр Ривилис
До чьего утра? :)))))))))))
Та-а-к энное количество лет назад я допустил "конкретный" ляп. Почему не вскрылось? Не знаю. Может не дошло до цеха. Может дошло, но рабочие по доброте душевной не воздали мне.
Значится так. Есть, как минимум, две схемы:
1. Линии параллельны и горизонтальны/вертикальны. Здесь нет проблем. Эта часть корректно работает.
2. Линии не параллельны.
Первая точка равноудаленной линии- это пересечение исходных
линий. Есть такая привязка в AutoCAD. Потом направить под углом 1/2 угла между исходными линиями на длину...на длину допустим равной наибольшей длине одной из линий. Нет . На длину равной средней длине этих линий. Можно это безболезненно изложить в LISP? Если нет. То придется уравнение линейное как то оформить.
Что скажете? ...В LISP есть какие либо библиотеки? Так. Надо учить матчасть. А именно, калькулятор, о котором пишет Владимир Свет. Мне кажется там много чего полезного имеется.
Вот какие построения надо выполнить вручную.
Первый способ.
1. Отрезки пересекаютя.
Из точки пересечения отрезков строится окружность с радиусом равным длине меньшего отрезка (а для программы - с радиусом равным полусумме длин отрезков). Внешняя часть круга обрезается. Строится отрезок от точки пересечения исходных отрезков до середины дуги между ними. Дуга стирается, а новый отрезок удлиняется с помощью, например, команды "_LENGTHEN" ("УВЕЛИЧИТЬ") или "_EXTEND" ("УДЛИНИТЬ").
2. Отрезки не пересекаются. Строится окружность из кажущейся точки пересечения отрезков с помощью привязки "_appint" ("каж") с радиусом см. выше. Далее те же действия, что и в случае 1, только новый отрезок строится из кажущейся точки пересечения исходных отрезков.
Следовательно, нужна проверка на пересечение отрезков.
Второй способ.
Определяется углы наклона исходных отрезков к оси X. Новый отрезок строится из точки пересечения (или из кажущейся точки пересечения) исходных отрезков под углом, равным полусумме углов этих отрезков с длиной, равной длине (или кажущейся длине) одного из отрезков. Forma писал о том же. Здесь ничего обрезать и стирать не надо, однако нужна проверка на направление векторов исходных отрезков. Для построения на экране первый способ лучше. Для программирования второй способ лучше. Но в первом случае не нужна проверка направления векторов.
Чтобы отправить ответ, вы должны войти или зарегистрироваться
Форумы CADUser → Программирование → Настройка меню и DIESEL → Макрос на кнопку "Равноудаленная линия"
Форум работает на PunBB, при поддержке Informer Technologies, Inc