Создание размерного стиля
В предыдущей части был рассмотрен вариант создания текстового стиля. Там все достаточно просто и универсально: хоть через entmake, хоть через ActiveX: как хочешь, так и создавай. С размерным стилем ситуация немного иная...
Я не знаю, почему, но факт остается фактом: ActiveX-методов настройки (не создания, а именно настройки!) размерного стиля не существует. Поэтому приходится разбираться именно с dxf-представлением и работать с ним.
Рассмотрим DXF-представление размерного стиля (пока рассматривается только один размерный стиль, без т.н. "подчиненных" - о них разговор впереди).
Если честно, я не хотел бы полностью дублировать DXF Reference - там все описано достаточно четко. Кроме нескольких моментов, которые лично я в свое время не сразу понял.
Это касается групп 5 (dimblk), ныне 342; 341, 343 и 344 группы. С группой 340 такой проблемы не возникло.
Напомню, что каждая из этих групп регулирует.
Группа | Пояснение | ||
340 | ename-указатель на текстовый стиль, используемый в размерном для простановки значений. Можно получить как
|
||
341 | ename-указатель на описание блока, используемого в качестве засечки для выносок (leader). Получить можно как
|
||
342..344 | То же, что и предыдущая строка, но уже как засечки для обычных размеров |
Казалось бы, все просто и ненавязчиво. Сначала создается текстовый стиль, потом на него получается указатель и вставляется в 340 группу. Только вот указатели на описания блоков портят радужность картины...
Блок, используемый в качестве засечки, на момент создания размерного стиля уже должен существовать в файле. Поэтому попробуем сделать так:
Внимание! Код заменен 2019-12-16 на корректно работающий.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | (vl-load-com) (defun _lispru-get-or-create-dimblock (name / err dimblk) ;| * Получение ename-указателя или создание блока с переданным именем * Если name попадает под стандартные наименования: "" || "_DOT" || "_DOTSMALL" || "_DOTBLANK" || "_ORIGIN" || || "_ORIGIN2" || "_OPEN" || "_OPEN90" || "_OPEN30" || || "_CLOSED" || "_SMALL" || "_NONE" || "_OBLIQUE" || || "_BOXFILLED" || "_BOXBLANK" || "_CLOSEDBLANK" || "_DATUMFILLED" || || "_DATUMBLANK" || "_INTEGRAL" || "_ARCHTICK" * То используется механизм через (setvar / getvar). В противном случае получается * указатель на имеющийся блок с таким именем. Если такого блока нет, он создается * пустым. * Примеры вызова: (_lispru-get-or-create-dimblock "qwert") (_lispru-get-or-create-dimblock "archtick") |; (cond ((wcmatch (strcase (vl-string-left-trim "_" name)) (strcat """,DOT,DOTSMALL,DOTBLANK,ORIGIN,ORIGIN2," "OPEN,OPEN90,OPEN30,CLOSED,SMALL," "NONE,OBLIQUE,BOXFILLED,BOXBLANK,CLOSEDBLANK," "DATUMFILLED,DATUMBLANK,INTEGRAL,ARCHTICK" ) ;_ end of strcat ) ;_ end of wcmatch (if (vl-catch-all-error-p (setq err (vl-catch-all-apply (function (lambda () (setq dimblk (getvar "dimblk")) (if (= dimblk "") (setq dimblk ".") ) ;_ end of if (setvar "dimblk" (strcat "_" (vl-string-left-trim "_" name))) (setvar "dimblk" dimblk) (setq res (tblobjname "block" (strcat "_" (vl-string-left-trim "_" name)))) ) ;_ end of lambda ) ;_ end of function ) ;_ end of vl-catch-all-apply ) ;_ end of setq ) ;_ end of vl-catch-all-error-p (setq res (tblobjname "block" (getvar "dimblk"))) ) ;_ end of if (if res (cdr (assoc 330 (entget res))) ) ;_ end of if ) ((tblobjname "block" name) (cdr(assoc 330 (entget (tblobjname "block" "_archtick"))))) (t (vla-add (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object))) (vlax-3d-point '(0. 0. 0.)) name ) ;_ end of vla-add (cdr (assoc 330 (entget (tblobjname "block" name)))) ) ) ;_ end of cond ) ;_ end of defun |
В результате, например, создание стиля, использующего в качестве засечек архитектурные (_ArchTick), будет выглядеть наподобие:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | (entmakex (list (cons 0 "DIMSTYLE") (cons 100 "AcDbSymbolTableRecord") (cons 100 "AcDbDimStyleTableRecord") (cons 2 "DimStyleName") (cons 70 0) (cons 40 (getvar "dimscale")) ;dimscale (cons 41 2.5) ;dimsz (cons 42 0.625) ;dimexo (cons 43 3.75) ;dimdli (cons 44 1.25) ;dimexe (cons 45 0.5) ;dimrnd (cons 46 0.0) ;dimdle (cons 140 2.5) ;dimtxt (cons 141 -2.5) ;dimcen (cons 143 0.005) ;dimaltf (cons 145 0) ;dimtvp (cons 147 0.5) ;dimgap (cons 72 0) ;dimlim (cons 73 0) ;dimtih (cons 74 0) ;dimtoh (cons 77 1) ;dimtad (cons 78 8) ;dimzin (cons 79 2) ;dimazin (cons 170 0) ;dimalt (cons 172 1) ;dimtofl (cons 173 0) ;dimsah (cons 174 0) ;dimtix (cons 175 1) ;dimsoxd (cons 176 0) ;dimclrd (cons 177 0) ;dimclre (cons 178 0) ;dimclrt (cons 179 1) ;dimadec (cons 271 0) ;dimdec (cons 272 0) ;dimtdec (cons 275 1) ;dimaunit (cons 277 2) ;dimlunit (cons 278 44) ;dimdsep (cons 279 0) ;dimtmove (cons 280 0) ;dimjust (cons 281 0) ;dimsd1 (cons 282 0) ;dimsd2 (cons 283 0) ;dimtolj (cons 284 8) ;dimtzin (cons 288 0) ;dimupt (cons 340 (tblobjname "style" (getvar "textstyle"))) ;dimtxtsty (cons 371 -2) ;dimlwd (cons 372 -2) ;dimlwe (cons 342 (_lispru-get-or-create-dimblock "_ArchTick")) (cons 343 (_lispru-get-or-create-dimblock "_ArchTick")) (cons 344 (_lispru-get-or-create-dimblock "_ArchTick")) ) ;_ end of list ) ;_ end of setq |
Наверняка каждый видел картинку наподобие
Обратите внимание: для стиля SPDS есть так называемые "подстили", отвечающие за создание угловых размеров, обозначений радиусов, диаметров и выносок. Это регулируется, как ни странно, всего лишь именем стиля. Если основное имя размерного стиля получилось, например, "SPDS" (как на рисунке), то для угловых размеров, например, имя стиля будет "SPDS$2". Можно свести все в таблицу:
Символы, добавляемые к имени стиля | Создаваемый размер |
$0 | Линейные размеры |
$2 | Угловые размеры |
$3 | Диаметры |
$4 | Радиусы |
$6 | Ординатные размеры |
$7 | Выноски и допуски |
Под каждый "подстиль" могут существовать собственные настройки, и это нормально. Полный код создания размерного стиля я не пишу, оставляя эту задачу заинтересовавшимся.
Памятуя о том, что ActiveX-варианта представления размерного стиля не существует, настройку существующего размерного стиля придется осуществлять только через subst. Без вариантов.
По функции _lispru-get-or-create-dimblock. Во фрагменте кода не понятно, почему подряд идут 2 setvar'а? В первом как бы получается нет никакого смысла?
(setq dimblk (getvar "dimblk"))
(setvar "dimblk"
(strcat "_" (vl-string-left-trim "_" name))
)
(setvar "dimblk" dimblk)
И ещё. В моём русском Автокаде 2008 твой код в частности ведёт себя так:
_$ (_lispru-get-or-create-dimblock "archtick")
nil
_$ (getvar "dimblk")
"Засечка"
_$
Так обратно-то надо вернуть
Насчет "перевода" значений системных переменных (убил бы локализаторов!):
Команда: DIMBLK
Новое значение DIMBLK, или . если по умолчанию < "Нет">:
Команда: (setvar "dimblk""_ArchTIck")
"_ArchTIck"
Команда: DIMBLK
Новое значение DIMBLK, или . если по умолчанию < "ДвЗасечка">:
Почему функция вернула nil - пока не понял, надо разбираться.
>Я не знаю, почему, но факт остается фактом: ActiveX-методов настройки (не создания, а именно >настройки!) размерного стиля не существует
Это не факт, это Ваше предположение.
'изменение размерных стилей
Public Sub testDimStyle()
Dim acDimStyle As AcadDimStyle
Set acDimStyle = ThisDrawing.DimStyles.Item(0)
ThisDrawing.ActiveDimStyle = acDimStyle
Call ThisDrawing.SetVariable("DIMTXSTY", "Текстовый_Стиль2")
acDimStyle.copyFrom ThisDrawing
End Sub
Отлично. Повторюсь: задача - настроить размерный стиль. Еще раз подчеркиваю - НАСТРОИТЬ!!! Установить засечки, их размер, установить текстовый стиль, аннотативность и т.п. Причем все (ну или какая-то часть) этих настроек должна отличаться от настроек предыдущего стиля.
В приведенном выше примере я как раз и настраиваю. Подчеркиваю - НАСТРАИВАЮ СУЩЕСТВУЮЩИЙ размерный стиль!!! Устанавливаю для него новый текстовый стиль с именем "Текстовый_Стиль2".
Хорошо, уговорили
Слегка пришлось подправить _lispru-get-or-create-dimblock :
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
(defun _lispru-get-or-create-dimblock (name / err dimblk)
;|
* Получение ename-указателя или создание блока с переданным именем
* Если name попадает под стандартные наименования:
"" || "_DOT" || "_DOTSMALL" || "_DOTBLANK" || "_ORIGIN" ||
|| "_ORIGIN2" || "_OPEN" || "_OPEN90" || "_OPEN30" ||
|| "_CLOSED" || "_SMALL" || "_NONE" || "_OBLIQUE" ||
|| "_BOXFILLED" || "_BOXBLANK" || "_CLOSEDBLANK" || "_DATUMFILLED" ||
|| "_DATUMBLANK" || "_INTEGRAL" || "_ARCHTICK"
* То используется механизм через (setvar / getvar). В противном случае получается
* указатель на имеющийся блок с таким именем. Если такого блока нет, он создается
* пустым.
* Примеры вызова:
(_lispru-get-or-create-dimblock "qwert")
(_lispru-get-or-create-dimblock "archtick")
|;
(cond ((wcmatch (strcase (vl-string-left-trim "_" name))
(strcat """,DOT,DOTSMALL,DOTBLANK,ORIGIN,ORIGIN2,"
"OPEN,OPEN90,OPEN30,CLOSED,SMALL,"
"NONE,OBLIQUE,BOXFILLED,BOXBLANK,CLOSEDBLANK,"
"DATUMFILLED,DATUMBLANK,INTEGRAL,ARCHTICK"
) ;_ end of strcat
) ;_ end of wcmatch
(if (vl-catch-all-error-p
(setq err (vl-catch-all-apply
(function (lambda ()
(setq dimblk (getvar "dimblk"))
(if (= dimblk "")
(setq dimblk ".")
) ;_ end of if
(setvar "dimblk" (strcat "_" (vl-string-left-trim "_" name)))
(setvar "dimblk" dimblk)
(setq res (tblobjname "block" (strcat "_" (vl-string-left-trim "_" name))))
) ;_ end of lambda
) ;_ end of function
) ;_ end of vl-catch-all-apply
) ;_ end of setq
) ;_ end of vl-catch-all-error-p
(setq res (tblobjname "block" (getvar "dimblk")))
) ;_ end of if
(if res
(cdr (assoc 330 (entget res)))
) ;_ end of if
)
((tblobjname "block" name) (cdr(assoc 330 (entget (tblobjname "block" "_archtick")))))
(t
(vla-add (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object)))
(vlax-3d-point '(0. 0. 0.))
name
) ;_ end of vla-add
(cdr (assoc 330 (entget (tblobjname "block" name))))
)
) ;_ end of cond
) ;_ end of defun
Функция может вернуть nil, если планируется использовать залитую стрелку: у этого блока мне пока не удалось получить указатель. Поэтому при entmake / entmakex придется пройтись по списку и "выкинуть" точечные пары, у которых второй элемент nil. vl-remove-if-not, к примеру, и вперед.
Спасибо Browning Zed, который выполнил вменяемое тестирование на https://forum.dwg.ru/showthread.php?p=1842474 ! В исходный пост внесены корректировки, на мой код в комментариях можно не смотреть.