Реклама i
Стань нашим партнером - зарабатывай с нами!
| Правила | Регистрация | Пользователи | Поиск | Сообщения за день | Все разделы прочитаны |  Справка по форуму | Файлообменник |

Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > LISP > Лисп простой пользовательской выноски

Лисп простой пользовательской выноски

Ответ
Поиск в этой теме
Непрочитано 21.03.2016, 10:37
Лисп простой пользовательской выноски
Сет
 
Регистрация: 19.11.2014
Сообщений: 2,435

Указал в заголовке, что речь о простой выноске, но может она и не простая. Прошу помощи в реализации, если это просто решается или подсказать направление куда думать, если сложная реализация.

Внешний вид выноски представлен на картинке во вложении.

Порядок запросов на ввод пользователя:
1. Введите верхний текст.
2. Укажите первую точку выноски.
3. Укажите вторую точку выноски.
4. Укажите третью точку выноски.

Как это должно работать.
1. Выноска должна быть ВСЕГДА на определенном слое, даже если активен другой. Изменить слой можно только вручную.
2. Выносная линия - это полилиния нулевой шириной, ее толщина определяется по слою.
3. Текст - вероятно мультитекст, так как нужно выравнивание. Шрифт текста, высота текста и отступ от полки - фиксированы в программе.
4. Положение текста определяется автоматически, в зависимости от введенных значений точек и выравнивается по краю горизонтальной полки.
5. В процессе задания точек хотелось бы видеть промежуточные сегменты, как это видно при отрисовке, например, полилинии. Промежуточная отрисовка текста - не важна.
6. Задание точек должно реагировать на режим ОРТО.
7. Ввод нижнего текста должен быть опциональным. Не знаю можно ли это реализовать без дополнительного запроса на нижний текст. По умолчанию текста нет.
8. Отрисовка точки на конце выноски - тоже опциональна. По идее можно сделать дополнительный запрос на точку, но хотелось бы, чтобы всегда работало значение по умолчанию - без точки. А если она нужна - это бы задавалось как-то дополнительно.

Миниатюры
Нажмите на изображение для увеличения
Название: Безымянный.png
Просмотров: 340
Размер:	2.5 Кб
ID:	167235  

Просмотров: 18331
 
Автор темы   Непрочитано 27.03.2016, 17:25
#61
Сет


 
Регистрация: 19.11.2014
Сообщений: 2,435


Цитата:
Сообщение от VVA Посмотреть сообщение
Сделай ее "псевдовертикальной". Сделай отступ по Х в нужную (в данном случае влево) для тебя сторону на несущественное для тебя значение (например на 0.001).
То есть ты имеешь ввиду фактически линию сделать наклонной? Хотелось бы, чтобы геометрия вертикальной линии была идеальной, т.е. без сдвигов даже на 0.001.
Сет вне форума  
 
Непрочитано 27.03.2016, 17:55
#62
Сергей812


 
Регистрация: 10.08.2013
Сообщений: 11,004


Пишите свой вариант выноски тогда

----- добавлено через ~2 мин. -----
если нужен узкоспециализированный вариант с идеально-вертикальной линией - тогда тот же динблок
Сергей812 вне форума  
 
Автор темы   Непрочитано 27.03.2016, 18:14
#63
Сет


 
Регистрация: 19.11.2014
Сообщений: 2,435


Цитата:
Сообщение от Сергей812 Посмотреть сообщение
Пишите свой вариант выноски тогда
Я бы написал, если бы понимал как заставить полку рисоваться слева от последней точки выноски.

Попутно возник еще один вопрос. Я реализую указание параметров выноски через диалоговое окно. Сначала использовал в качестве кнопок выхода из диалога стандартную пару ok_cancel. Но эти кнопки разной ширины, захотел немного подравнять это дело. Пишу такой код вместо ok_cancel:
Код:
[Выделить все]
 : row { 
    : button {label="OK"; key="accept"; action="(done_dialog)";}
    : button {label="Отмена"; key="cancel";}} 
Но в таком виде диалог просто не отображается. Автокад выдает сообщение, что у диалога нет кнопок OK или Cancel. То есть как бы однажды появившись этот диалог не может быть закрыт.
Сет вне форума  
 
Непрочитано 27.03.2016, 18:19
1 | #64
Boxa

КЖ; C#
 
Регистрация: 03.11.2005
Санкт-Петербург
Сообщений: 2,588


не знаю как это делается на лисп, но в C# направление выноски устанавливается как то так:
Код:
[Выделить все]
 
 // Вот сюда запихнуть правую-левую привязку текста
if (mLandingLocation.X < mArrowLocation.X)
{
  Entity.SetDogleg(0, new Vector3d(-1, 0, 0));
}else{
  Entity.SetDogleg(0, new Vector3d(1, 0, 0));
}
Entity - MLeader
mLandingLocation - положение текста
mArrowLocation - положение указателя

Возможно вам это поможет.
Boxa вне форума  
 
Автор темы   Непрочитано 27.03.2016, 18:46
#65
Сет


 
Регистрация: 19.11.2014
Сообщений: 2,435


Я уже пытался с этими Dogleg'ами что-то сделать - ничего путного не получается, да и смысл этого свойства не очень понятен. Я задаю это свойство в двух вариантах:
Код:
[Выделить все]
 (vla-SetDoglegDirection mleader 0 (vlax-3D-point '(1 0 0)))
(vla-SetDoglegDirection mleader 0 (vlax-3D-point '(-1 0 0)))
В первом случае выносная линия отклоняется от вертикали, смещаясь влево, полка находится справа.
Во втором случае выносная линия отклоняется от вертикали вправо, полка находится слева.

----- добавлено через ~13 мин. -----
По второму варианту верх выносной линии уходит вправо визуально на ширину мультитекста. С помощью ручки выносную линию можно вернуть в вертикальное положение, при этом полка остается слева, как мне и нужно. Вопрос - каким образом получить доступ к этой точке мультивыноски, чтобы переместить ее программно?
Сет вне форума  
 
Автор темы   Непрочитано 27.03.2016, 19:02
#66
Сет


 
Регистрация: 19.11.2014
Сообщений: 2,435


Для лучшего понимания добавлю картинку. Первая выноска - это при вставке. Вторая - вручную отредактированная с помощью ручки (та, которая в красном кружке). Вот ее-то и нужно программно сдвинуть.

----- добавлено через ~3 ч. -----
Цитата:
Сообщение от VVA Посмотреть сообщение
Сделай отступ по Х в нужную (в данном случае влево) для тебя сторону на несущественное для тебя значение (например на 0.001).
Я попробовал этот способ - он не работает. Смещал точку даже на 1000 влево - все равно полка рисуется справа.
Миниатюры
Нажмите на изображение для увеличения
Название: Безымянный.png
Просмотров: 27
Размер:	5.1 Кб
ID:	167628  
Сет вне форума  
 
Непрочитано 27.03.2016, 22:01
#67
skkkk


 
Регистрация: 20.03.2008
Сообщений: 2,653


Сет, а если ее отзеркалить?
skkkk вне форума  
 
Автор темы   Непрочитано 27.03.2016, 22:09
#68
Сет


 
Регистрация: 19.11.2014
Сообщений: 2,435


Цитата:
Сообщение от skkkk Посмотреть сообщение
Сет, а если ее отзеркалить?
Была такая мысль, но отзеркаливание годится только для простых выносок, как на картинке. Если же выноска многосегментная (я усложнил себе задачу), то отзеркаливание не годится, так как отзеркалится вся геометрия сложной выноски.

Сейчас размышляю над двумя возможностями.

1. Использовать как-то SetLeaderLineVertices, но пока ничего дельного не выходит.
2. Выяснить координаты последней точки выноски (которая автоматически смещается, она в красном кружке на картинке) через GetLeaderLineVertices и с помощью команды РАСТЯНУТЬ сдвинуть ее на необходимую величину влево. Во всяком случае вручную этот способ работает, но как это сделать программно - пока не понимаю.

----- добавлено через ~24 мин. -----
Кажется разобрался с первым способом. работает вот такая конструкция:
Код:
[Выделить все]
 (vla-SetLeaderLineVertices mleader 0 mleader_points)
mleader - vla-объект мультивыноска
0 - индекс выносной линии (у меня предусмотрена всего одна выносная линия, значит 0)
mleader_points - массив safearray из вариантов с типа vbDouble с координатами вершин мультивыноски
Сет вне форума  
 
Автор темы   Непрочитано 27.03.2016, 23:38
#69
Сет


 
Регистрация: 19.11.2014
Сообщений: 2,435


Ну что ж, вот что у меня получилось.

Код:
[Выделить все]
 cs_leader_dialog: dialog
{
  label="Выноска";
  initial_focus="k_top_text"; 
  : row
  {
    : edit_box {key="k_top_text"; width=30;}
    : text {label="Верхний текст";}
  }
  : row
  {
    : edit_box {key="k_bottom_text"; width=29;}
    : text {label="Нижний текст";}
  }
  : row
  {
    : popup_list {key="k_layer"; width=20;}
    : text {label="Слои";}
  }
  : row
  {
    height=2;
    : toggle {alignment="bottom"; label="Рисовать точку"; key="k_dot"; value="0";}
  }   
  ok_cancel; 
}


Код:
[Выделить все]
 (vl-load-com)
(setq acad_application (vlax-get-acad-object))
(setq active_document (vla-get-ActiveDocument acad_application))
(setq model_space (vla-get-ModelSpace active_document))

(setq default_top_text "")
(setq default_bottom_text "")
(setq default_layer "")
(setq default_draw_dot "0")

(defun c:cs_leader (/ dcl_id
		      layers
		      count_layers
		      active_layer
		      layer
		      i
		      p1		     
		      p2
		      points
		      count_points
		      enter_point
		      polyline
		      polyline_points
		      mleader
		      mleader_points
		      p_left
		      p_right
		      polka_length
		      text_length)
  (setq dcl_id (load_dialog "D:\\MyAutoCAD\\cs_leader.dcl"))
  (new_dialog "cs_leader_dialog" dcl_id)
  (set_tile "k_top_text" default_top_text)
  (set_tile "k_bottom_text" default_bottom_text)
  (set_tile "k_dot" default_draw_dot)
  ;;; заполнение списка слоев
  (start_list "k_layer")
  (setq layers (vla-get-Layers active_document))
  (setq count_layers (vla-get-Count layers))
  (setq active_layer -1)
  (setq i 0)
  (repeat count_layers
    (setq layer (vla-get-Name (vla-Item layers i)))
    (if (= layer default_layer) (setq active_layer i))	  
    (add_list layer)
    (setq i (1+ i))
  ) ; repeat
  (end_list)
  (if (>= active_layer 0) (set_tile "k_layer" (itoa active_layer)))
  ;;; конец заполнения списка слоев
  (action_tile "k_top_text" "(setq default_top_text $value)")
  (action_tile "k_bottom_text" "(setq default_bottom_text $value)")
  (action_tile "k_dot" "(setq default_draw_dot $value)")
  (action_tile "accept" "(setq default_layer (vla-get-Name (vla-Item layers (atoi (get_tile \"k_layer\")))))
                         (done_dialog)")
  (action_tile "cancel" "(exit)") 
  (start_dialog)
  (unload_dialog dcl_id)
  (setq p1 (getpoint "\nУкажите точку выноски:"))
  (setq points p1)
  (setq enter_point 1)
  (while (= enter_point 1)
    (setq p2 (getpoint p1 "\nУкажите следующую точку:"))
    (if (null p2)
        (progn		
          (setq enter_point 0)	  
        ) ; progn
        (progn
          (setq points (append points p2))
	  (setq p1 p2)
	  (if (/= polyline nill) 
	    (if (not (vlax-erased-p polyline)) (vla-Delete polyline))
	  ); if
	  (setq polyline_points (vlax-make-safearray vlax-vbDouble (cons 0 (1- (length points)))))
          (vlax-safearray-fill polyline_points points)
          (setq polyline (vla-AddPolyline model_space polyline_points))
	  (vla-put-Layer polyline default_layer)
        ) ; progn
    ) ; if
  ) ; while
  ;;; определяем длину полки
  (setq p2 (getpoint p1 "\nУкажите точку конца полки:"))
  (if (null p2)
    (progn		
      (setq p2 (cadr (grread T)))
    ) ; progn
    (progn		
      (setq polka_length (abs (- (car p1) (car p2))))
    ) ; progn
  ) ; if
  
  ;;; рисуем мультивыноску
  (setq mleader_points (vlax-make-safearray vlax-vbDouble (cons 0 (1- (length points)))))
  (vlax-safearray-fill mleader_points points)
  (setq mleader (vla-AddMLeader model_space mleader_points 0))
  ;;; устанавливаем слой
  (vla-put-Layer mleader default_layer)
  ;;; выравниваем текст по центру
  (vla-put-TextJustify mleader acAttachmentPointMiddleCenter)
  ;;; рисуем текст
  (vla-put-TextString mleader (strcat "\\pxa0.2,se0.87;" default_top_text "\\P\\pa0;" default_bottom_text))
  ;;; рисуем или не рисуем точку
  (if (= default_draw_dot "1") (vla-put-ArrowheadType mleader acArrowDot))
  ;;; устанавливаем длину полки
  (vla-GetBoundingBox mleader 'p_left 'p_right)
  (setq p_left (vlax-safearray->list p_left))
  (setq p_right (vlax-safearray->list p_right))
  (setq text_length (abs (- (car p_left) (car p_right))))
  (if (> polka_length text_length)
    (vla-put-DoglegLength mleader (/ (- polka_length text_length) 100))  
    (vla-put-DoglegLength mleader 1.5)
  ) ; if
  (if (> (car p1) (car p2))
    (progn
      (vla-SetDoglegDirection mleader 0 (vlax-3D-point '(-1 0 0)))
      (vla-SetLeaderLineVertices mleader 0 mleader_points)
    ) ; progn
  ) ; if
  ;;; удаляем временную линию
  (if (/= polyline nill)
    (if (not (vlax-erased-p polyline)) (vla-Delete polyline))
  ); if
  (princ)
) ; defun



Выноска корректно работает в прилагаемом чертеже, только в файле cs_leader.lsp нужно поправить путь к файлу cs_leader.dcl, в соответствии с тем местом, где вы его разместите.

Для использования функции в своем чертеже нужно учесть следующее:
1. Выноска строится с текущим стилем мультивыносок, поэтому нужно создать у себя такой же стиль мультивыносок, как в прилагаемом чертеже, ну или подкорректировать cs_leader.lsp.
2. В моем чертеже установлен масштаб 100 и если вы хотите использовать функцию в чертеже с другим масштабом - нужно будет подкорректировать cs_leader.lsp в месте, где задается DoglegLength (это размер полки от выносной линии до текста).

Как работать с функцией:
1. Активируем функцию командой cs_leader.
2. В появившемся диалоге устанавливаем необходимые параметры и жмем ОК.
3. Указываем точки выносной линии, которых должно быть не менее двух. Ввод точек завершаем нажатием Enter или ПКМ.
4. Идет запрос указания крайней точки полки. Возможны варианты:
4а. Указываем эту точку ЛКМ.
4б. Перемещаем курсор в ту сторону (относительно последней точки), куда хотим, чтобы откладывалась полка, жмем Enter или ПКМ.

Осталось нереализованным, но вроде как не сложным:
1. Автовключение режима ОРТО (я еще думаю, надо ли это).
2. Сохранение значений по умолчанию в файле, а не глобальных переменных.

Осталось нереализованным, но пока не особо понятным:
1. Обработка всевозможных нештатных ситуаций.
1а. Выход из программы по Esc - у меня остается временная линия, надо бы ее программно удалять.

Разметка диалога какая-то странная. Некоторые элементы при одинаковой длине почему-то занимают разную по размерам область на экране. Ну с этим-то я справился методом тыка, а вот с чем пока не справился, но хотелось бы:
1. Свободное пространство слева от элементов управления и справа почему-то разное. Хотелось бы, чтобы справа расстояние до края формы было такое же, как и слева (красные прямоугольники).
2. Две кнопки OK и Cancel заданы кодом ok_cancel и имеют разную ширину (синий прямоугольник). Хотелось бы их сделать одинаковыми. Но при замене ok_cancel на два button'а с именами "accept" и "cancel" почему-то приводит к сообщению Автокада об ошибке - ему нужно, чтобы в диалоге обязательно присутствовала кнопка выхода OK или Cancel.
Миниатюры
Нажмите на изображение для увеличения
Название: Безымянный.png
Просмотров: 72
Размер:	4.4 Кб
ID:	167643  
Вложения
Тип файла: dwg
DWG 2004
cs_leader.dwg (127.2 Кб, 18 просмотров)
Сет вне форума  
 
Непрочитано 28.03.2016, 06:44
#70
Boxa

КЖ; C#
 
Регистрация: 03.11.2005
Санкт-Петербург
Сообщений: 2,588


Цитата:
Сообщение от Сет Посмотреть сообщение
Я уже пытался с этими Dogleg'ами что-то сделать - ничего путного не получается, да и смысл этого свойства не очень понятен. Я задаю это свойство в двух вариантах:
Код:
[Выделить все]
 (vla-SetDoglegDirection mleader 0 (vlax-3D-point '(1 0 0)))
(vla-SetDoglegDirection mleader 0 (vlax-3D-point '(-1 0 0)))
В первом случае выносная линия отклоняется от вертикали, смещаясь влево, полка находится справа.
Во втором случае выносная линия отклоняется от вертикали вправо, полка находится слева.

----- добавлено через ~13 мин. -----
По второму варианту верх выносной линии уходит вправо визуально на ширину мультитекста. С помощью ручки выносную линию можно вернуть в вертикальное положение, при этом полка остается слева, как мне и нужно. Вопрос - каким образом получить доступ к этой точке мультивыноски, чтобы переместить ее программно?
Сразу в двух вариантах? зачем?
А на тему смещения.... если я правильно помню, это зависит от выравнивания текста.Т.е. для правильного отображения не достаточно назначить правильный вектор, нужно еще и выравнивание текста поменять и будет как то так:Видяшка
Boxa вне форума  
 
Автор темы   Непрочитано 28.03.2016, 09:33
#71
Сет


 
Регистрация: 19.11.2014
Сообщений: 2,435


Цитата:
Сообщение от Boxa Посмотреть сообщение
Сразу в двух вариантах? зачем?
Для тестирования эффекта.
В итоге вопрос решен.

----- добавлено через ~38 мин. -----
Появились новые "хотелки"

1. Как все-таки можно решить вопрос визуализации будущего текста мультивыноски? Устроил бы вариант хотя бы прямоугольником описывающим каким или другим примитивом, дающим представление о длине и высоте текста.
2. Можно ли при активации редактирования текста выноски двойным кликом автоматически выделять содержимое?
Сет вне форума  
 
Непрочитано 28.03.2016, 10:25
#72
Boxa

КЖ; C#
 
Регистрация: 03.11.2005
Санкт-Петербург
Сообщений: 2,588


Цитата:
Сообщение от Сет Посмотреть сообщение
Как все-таки можно решить вопрос визуализации будущего текста мультивыноски? Устроил бы вариант хотя бы прямоугольником описывающим каким или другим примитивом, дающим представление о длине и высоте текста.
Добро пожаловать на .net и JigEntity =о) В видяшке выше именно оно.
Цитата:
Сообщение от Сет Посмотреть сообщение
Можно ли при активации редактирования текста выноски двойным кликом автоматически выделять содержимое?
Не знаю, меня не напрягает нажать ctrl+A, хотя я стараюсь формировать содержание ДО того как делать выноску...
Boxa вне форума  
 
Автор темы   Непрочитано 28.03.2016, 12:01
#73
Сет


 
Регистрация: 19.11.2014
Сообщений: 2,435


Цитата:
Сообщение от Boxa Посмотреть сообщение
хотя я стараюсь формировать содержание ДО того как делать выноску
Довольно часто нужно менять ее содержимое ПОСЛЕ.
Сет вне форума  
Ответ
Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > LISP > Лисп простой пользовательской выноски

Размещение рекламы
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Комрады, не работает простой лисп по копированию отрезка. MegaMost LISP 10 07.09.2015 00:23
Как визуализировать создаваемый объект? Glorius Программирование 27 08.08.2015 22:59
мой первый лисп, выноска, пинайте! baaba LISP 17 20.10.2009 15:42
Помогите продумать поворот части выноски! Tonic Программирование 40 02.07.2007 20:21
Сброс связи линии выноски и MTEXTа выноски kabzzz AutoCAD 3 19.04.2006 12:57