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

Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > Автоматическое уменьшение шрифта мультитекста

Автоматическое уменьшение шрифта мультитекста

Ответ
Поиск в этой теме
Непрочитано 06.11.2009, 14:01 #1
Автоматическое уменьшение шрифта мультитекста
Нитонисе
 
Регистрация: 05.11.2009
Сообщений: 4,360

Допустим я рисую програмно мультитекст и мне нужно его вместить в одну строчку длиной 3000. Но текст при заданном размере шрифта не помещается в эту длину и переносится на вторую строчку. Хотелось бы отлавливать этот момент и програмно увеличивать степень сжатия шрифта, чтобы текст поместился в отведенную для него зону 3000 в одну строку. Как бы это сделать?

Добавлено.
Никто ничего не посоветовал, пришлось разбираться самому. Задачу решил, может коряво, но главное работает)
Если кому интересно - выложу работающий код, а так - просто опишу идею.

Создается мультитекст нужной мне длины.
Методом GetBoudingBox определяются диагональные точки описывающего этот текст прямоугольника.
По этим точкам можно определить высоту созданного текста.
Для "правильного" текста высота не должна быть больше 700 в моем случае, то есть это текст в одну строку, что мне и нужно.
Если же высота нарисованного текста оказалась больше - значит текст "неправильный" - в две строки.
В случае если вышел двустрочный мультитекст я создаю цикл, в котором текст удаляется, задается параметр его сжатия на 0.01 меньше и текст снова рисуется. Снова определяется его высота. И так жо тех пор, пока текст не сожмется на столько, чтобы уместиться в одну строчку.

Может вычислений много лишних получается, но результат красивый и скорость меня вполне устраивает)

Последний раз редактировалось Нитонисе, 07.11.2009 в 11:30.
Просмотров: 4464
 
Непрочитано 10.11.2009, 06:58
#2
Disney

Геодезист
 
Регистрация: 12.03.2009
Сибирь (где медведи по улицам ходят)
Сообщений: 860
Отправить сообщение для Disney с помощью Skype™


Метод GetBoudingBox, немного, точнее совсем не корректно, определяет диагональные точки для прямоугольника, описанного вокруг объекта(примитива) mtext.
Только в том случаи, данные будут верны, если пользовательская ширина (dxf пара код 41) и высота (dxf пара код 46) либо соответствуют действительным ширине (dxf пара код 42) и высоте (dxf пара код 43), либо равны 0, т.к. почему-то габариты определяются по ним (пользовательским размерам), по ним же отображаются и ручки при выделении mtext.
Поэтому проще и точнее, будет брать высоту созданного текста, сразу из 43 кода.
Миниатюры
Нажмите на изображение для увеличения
Название: GetBoudingBox.jpg
Просмотров: 130
Размер:	33.7 Кб
ID:	28511  
__________________
Почему все вдруг становятся умными, когда уже не надо?
Disney вне форума  
 
Автор темы   Непрочитано 10.11.2009, 11:30
#3
Нитонисе


 
Регистрация: 05.11.2009
Сообщений: 4,360


Disney

Возможно вы где-то и правы, но в одном месте ошиблись.
На вашем рисунке, в том мультитексте, где красной диагональю перечеркнут текст "первая строка" (второй ряд сверху, первый мультитекст слева), эта самая диагональ проведена неверно, потому что в этом случае высота мультитекста определяется полностью, с учетом второй строки. Именно этот случай работает в моей программе. Мне нужно чтобы текст помещался в одну строку и в этом случае он имеет определенную высоту. А как только текст перелазит на вторую строку, то я, пользуясь методом GetBoundingBox, определяю что высота мультитекста стала больше, что означает что в мультитексте появилась вторая строка. И в этом случае начинаю програмно увеличивать степень сжатия, до получения нужной мне высоты текста.
Нитонисе вне форума  
 
Непрочитано 10.11.2009, 13:13
#4
Do$

AutoCAD/Civil3D LISP/C#
 
Регистрация: 15.08.2008
Санкт-Петербург
Сообщений: 1,701
Отправить сообщение для Do$ с помощью Skype™


Подсмотрел как-то у Кулик Алексея aka kpblc такое решение: длина текста проверяется функцией textbox - без vla, просто и быстро. Причем примитива может и не существовать (что меня, собственно, и удивило ), то есть пересоздавать мультитекст не придется.
Do$ вне форума  
 
Непрочитано 10.11.2009, 13:21
#5
Disney

Геодезист
 
Регистрация: 12.03.2009
Сибирь (где медведи по улицам ходят)
Сообщений: 860
Отправить сообщение для Disney с помощью Skype™


Цитата:
Сообщение от Нитонисе Посмотреть сообщение
Disney

Возможно вы где-то и правы, но в одном месте ошиблись.
Я не ошибался, я же не в рукопашную их рисовал

Код:
[Выделить все]
(defun c:test (/ minPt maxPt)
  (vl-load-com)
  (vla-GetBoundingBox
    (vlax-ename->vla-object (car (entsel)))
    'minPt
    'maxPt
  )
  (entmake (list
	     '(0 . "LINE")
	     '(100 . "AcDbEntity")
	     '(62 . 1)
	     '(370 . 50)
	     '(100 . "AcDbLine")
	     (cons 10 (vlax-safearray->list minPt))
	     (cons 11 (vlax-safearray->list maxPt))
	   )
  )
  (entupd (entlast))
)
Цитата:
(второй ряд сверху, первый мультитекст слева),
Хорошо, при программном создании текста, такого скорее всего не бывает, т.к. высота автоматически изменяется по количеству строк(на картинке, я её(высоту) уже потом, руками изменил) а вот ширина нет, какой указали такой и будет, но она вас и не волнует.
Просто зачем лишние манипуляции с GetBoudingBox, берём значение dxf пары под кодом 40 (высота текста <этим значением, мы как правило задаём размер самого текста>)и значение dxf пары под кодом 43 (действительное значение высоты текста <т.е как бы сумма высот всех строк + межстрочный интервал>)
__________________
Почему все вдруг становятся умными, когда уже не надо?
Disney вне форума  
 
Автор темы   Непрочитано 10.11.2009, 13:53
#6
Нитонисе


 
Регистрация: 05.11.2009
Сообщений: 4,360


Цитата:
Сообщение от Disney Посмотреть сообщение
Хорошо, при программном создании текста, такого скорее всего не бывает, т.к. высота автоматически изменяется по количеству строк(на картинке, я её(высоту) уже потом, руками изменил) а вот ширина нет, какой указали такой и будет, но она вас и не волнует.
Да, ширина у меня фиксированная, а высота при програмной отрисовке "гуляет".
Цитата:
Сообщение от Disney Посмотреть сообщение
Просто зачем лишние манипуляции с GetBoudingBox, берём значение dxf пары под кодом 40 (высота текста <этим значением, мы как правило задаём размер самого текста>)и значение dxf пары под кодом 43 (действительное значение высоты текста <т.е как бы сумма высот всех строк + межстрочный интервал>)
Ну я тут спорить не буду, просто уже использовал вышеуказнный метод, который работает и скорость обработки данных меня устраивает))

Единственное что у меня в программе идет цикл - определяю высоту мультитекста, сравниваю с определенным значением, если сравнение не удовлетворяет моим нуждам, то увеличиваю степень сжатия текста на 0.01. И так до тех пор, пока текст не поместится в одну строку. Может быть есть какой-то альтернативный метод отрисовки такого мультитекста? Хотелось бы уйти от цикла, чтобы степень сжатия регулировалась автоматически при указании ширины.
Нитонисе вне форума  
 
Непрочитано 10.11.2009, 14:20
#7
Do$

AutoCAD/Civil3D LISP/C#
 
Регистрация: 15.08.2008
Санкт-Петербург
Сообщений: 1,701
Отправить сообщение для Do$ с помощью Skype™


Используем textbox для вычисления получающейся длины текста, потом делим желаемую длину текста на это значение и получаем к-т сжатия
Например, так:
Код:
[Выделить все]
(defun find-text-width (str h l / wdt)
		       ;|
  Функция нахождения коэффициента сжатия текста, чтобы он имел длину не больше указанной
  str - текстовая строка
  h - высота текста
  l - максимальная длина текста
  Пример:
  (find-text-width "Тут я пишу всякую лабуду которая мне пришла в голову!" 10 40)
  ->0.078
  |;
  (setq wdt 1.0)
  (if (and (= (type str) 'STR) (numberp h) (numberp l))
    (/ (+ 1
	  (fix (* 1000
		  (/ l
		     (apply '(lambda (a b) (- (car b) (car a)))
			    (textbox (list (cons 40 h)
					   (cons 1 str)
					   (cons 41 wdt)
					   (cons 10 '(0. 0. 0.))
					   (cons 210 '(0. 0. 1.))
				     ) ;_ end of list
			    ) ;_ end of textbox
		     ) ;_ end of apply
		  ) ;_ end of /
	       ) ;_ end of *
	  ) ;_ end of fix
       ) ;_ end of +
       1000.0
    ) ;_ end of /
    (princ "\nНеправильный тип данных!")
  ) ;_ end of if
) ;_ end of defun

Последний раз редактировалось Do$, 10.11.2009 в 14:38.
Do$ вне форума  
 
Автор темы   Непрочитано 10.11.2009, 15:14
#8
Нитонисе


 
Регистрация: 05.11.2009
Сообщений: 4,360


Do$
Да, все работает и без цикла. Надо будет прикрутить все это в свою программу) Спасибо.
Нитонисе вне форума  
 
Непрочитано 10.11.2009, 15:32
#9
Кулик Алексей aka kpblc
Moderator

LISP, C# (ACAD 200[9,12,13,14])
 
Регистрация: 25.08.2003
С.-Петербург
Сообщений: 40,406


Do$, для textbox и многострочного текста подобная конструкция может и не сработать: во-первых, при наличии в тексте принудительных переводов строк у меня в 2008 вываливает ошибку; во-вторых, в многострочнике текст может содержаться не только в группе 1. Хотя для коротких (до 255 символов) текстов подобное работает "на ура"
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Непрочитано 10.11.2009, 15:59
#10
Do$

AutoCAD/Civil3D LISP/C#
 
Регистрация: 15.08.2008
Санкт-Петербург
Сообщений: 1,701
Отправить сообщение для Do$ с помощью Skype™


Нитонисе, пожалуйста!
Кулик Алексея aka kpblc как я себе представляю: применять эту функцию следует до создания мультитекста!
То есть, иными словами, функция служит для выяснения: какой коэффициент сжатия нужно задать тексту текущего стиля, чтобы заданная строка уместилась в заданной длине. А вот корректно ли будет извлечена строка из мтекста и загнана в функцию - это уже не моя головная боль
Do$ вне форума  
Ответ
Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > Автоматическое уменьшение шрифта мультитекста



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Обсуждение моего шрифта Никита В. Разное 36 29.05.2008 16:53
Вопрос о стандарте на высоту шрифта Илья V. Поиск литературы, чертежей, моделей и прочих материалов 5 05.05.2008 20:25