Как найти координаты поля в тексте

Автор Тема: Как найти координаты поля в тексте  (Прочитано 1267 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Владимир ШуАвтор темы

  • ADN Club
  • *****
  • Сообщений: 614
  • Карма: 156
    • ПГСу Бложик
При проверке файлов, нормоконтролер помечает (обводит) неправильные фрагменты, к таким фрагментам относятся, в том числе, и сломанные поля.
И если найти все поля в чертеже не проблема, найти сломанные поля, так же не сложно, найти внутри каких объектов находятся поля так же не сложно, то вот как найти координаты самих полей, вот тут у меня затык.
К сожалению координаты и границы объекта внутри которого находится сломанное поле не подходят, так как это может быть MText, с портянкой на 2-3 страницы.

Собственно вопрос в заголовке темы, как найти координаты поля или как найти координаты любой буквы в тексте

P.S.
Я порылся в методах и свойствах как самого класса Field, так и его родителя DBObject, но все что там могло мне помочь, это Bounds, но естественно эти поля не заполнены.

Код - C# [Выбрать]
  1.       App.Document doc = App.Application.DocumentManager.MdiActiveDocument;
  2.       if (doc == null) { return; }
  3.  
  4.       Db.Database db = doc.Database;
  5.       Ed.Editor ed = doc.Editor;
  6.  
  7.  
  8.       var opt = new Ed.PromptEntityOptions("\nSelect an MText object containing field(s): ");
  9.       opt.SetRejectMessage("\nObject must be MText.");
  10.       opt.AddAllowedClass(typeof(Db.MText), false);
  11.  
  12.       Ed.PromptEntityResult res = ed.GetEntity(opt);
  13.  
  14.       if (res.Status != Ed.PromptStatus.OK) { return; }
  15.  
  16.  
  17.       using (Db.Transaction Tx = db.TransactionManager.StartTransaction())
  18.       {
  19.         var mtext = Tx.GetObject(res.ObjectId, Db.OpenMode.ForRead) as Db.MText;
  20.  
  21.         if (!mtext.HasFields)
  22.         {
  23.           ed.WriteMessage("\nObject does not contain fields.");
  24.           return;
  25.         }
  26.  
  27.         Db.ObjectId id = mtext.GetField();
  28.         Db.Field fieldBase = Tx.GetObject(id, Db.OpenMode.ForRead) as Db.Field;
  29.        
  30.         var fields = fieldBase.GetChildren();
  31.         foreach (var field in fields)
  32.         {
  33.           if (field.EvaluationStatus.Status != Db.FieldEvaluationStatus.Success)
  34.           {
  35.             if (field.Bounds != null)
  36.             {
  37.               //он всегда null
  38.               var pnt = field.Bounds.Value.MinPoint;
  39.             }
  40.  
  41.            
  42.             if(field.Drawable.Bounds != null)
  43.             {
  44.               // и этот всегда null
  45.             }
  46.  
  47.             ed.WriteMessage("\nЕсть проблемки!");
  48.  
  49.           }
  50.         }
  51.         Tx.Commit();
  52.       }

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 814
  • Карма: 166
    • Мои плагины к Автокаду
Re: Как найти координаты поля в тексте
« Ответ #1 : 05-05-2024, 10:51:50 »
Серьезная задачка. Я бы попробовал создать новый MText со всем содержимым старого ДО начала кода поля и попытаться понять, где конец текста получился. И еще один MText чисто с кодом неработающего поля для расчета его размеров. Конечно куча проблем вылезет с оборвавшимся форматированием и многострочными текстами...

Оффлайн Владимир ШуАвтор темы

  • ADN Club
  • *****
  • Сообщений: 614
  • Карма: 156
    • ПГСу Бложик
Re: Как найти координаты поля в тексте
« Ответ #2 : 05-05-2024, 12:56:46 »
я пробовал получать фрагменты MText через mtext.ExplodeFragments( new Db.MTextFragmentCallback(MTextCallback)); с сохранением во внешний список расположение фрагмента, его содержание и размер и с последующим поиском в полученных фрагментах значения поля (string value = field.GetStringValue();), но это так коряво и при наличие множества битых полей не надежно, да и положение получается не отдельного поля, а строки в MTextе

В общем что то не получается =(

Оффлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 536
  • Карма: 117
Re: Как найти координаты поля в тексте
« Ответ #3 : 07-05-2024, 10:31:15 »
В общем что то не получается =(
Можно попробовать следующее.

не знаю как через API, но при разбивке MText через (_explode)
MText разбивается на строки DBText и вместо поля в DBText вставляется его значение.
Тут важно проверить, знаешь ли ты значение значение в MText "сломанного поля" до разбивки и что при разбивке такого поля происходит, сохраняется ли значение, не происходит ли смещения и т.д.

Если после разбивки на DBText значение поля не изменилось и не сместилось, можно попробовать следующее:
DBText дробится на несколько DBText, если в MText используются теги, например подчеркивание

Экспериментировал с тегом даты:
В MText было: "\A1;{\W1;\Lмая 7, 2024}"
В DbText стало: "%%Uмая 7, 2024"

Т.е. логика такая:
1. находишь значение сломанного поля, например "мая 7, 2024",
2. оборачиваешь поле в тег подчеркивания "\A1;{\W1;\Lмая 7, 2024}". (можно попробовать тег цвета, шрифта и т.д.)
3. Разбиваешь MText
4. Ищешь последние добавленные DbText с нужным значением поля "%%Uмая 7, 2024" или "мая 7, 2024"
5. Определяешь координаты


Оффлайн Владимир ШуАвтор темы

  • ADN Club
  • *****
  • Сообщений: 614
  • Карма: 156
    • ПГСу Бложик
Re: Как найти координаты поля в тексте
« Ответ #4 : 14-05-2024, 08:22:05 »
Получилось. Публиковать простыню кода не хочется, а внятно сформулировать алгоритм у меня не выходит...
В общем все построено вокруг:
mtextObj.ExplodeFragments(MTextFragmentCallback enumerator, object userData) - для получения строк без форматирования и с координатами начала
Db.Field.FindField(mtext.getMTextWithFieldCodes(), sInt, ref stridx, ref endIdx) - поиска индексов начала и конца поля
Autodesk.AutoCAD.Internal.Utils.GetTextExtents(mtext.TextStyleId, str, mtext.TextHeight) - вычисление смещения от начала строки и поиск размеров самого поля


Но есть и косяк... mtextObj.ExplodeFragments() теряет пустые строки из-за чего может возникать некоторое смещение координат поля... но для меня это не критично, так что пусть.
Однако, если очень нужно будет, то можно попробовать для очистки текста использовать  Db.TextEditor te = Db.TextEditor.CreateTextEditor(tMtext)
и после очистки пустые строки можно будет учесть