Збереження неграфічні інформації в. dwg-кресленнях

    image
 
Кожен розробник додатків САПР рано чи пізно стикається з проблемою зберігання в кресленні допоміжної неграфічні інформації. Це можуть бути атрибути окремих графічних елементів, атрибути окремих аркушів, або ж налаштування всього креслення. На відміну від атрибутів блоку, ця інформація не видна користувачеві і застосовується для програмної обробки креслень.
 
На сьогоднішній день існує ряд традиційних способів вирішення задачі: це додавання XData до елементів креслення, використання XRecord і створення власних неграфічних об'єктів.
  
У порівнянні з традиційними, механізм створення та зберігання неграфічні інформації в MultiCAD.NET API набагато компактніші і зручніше у використанні. Крім того, він універсальний і може бути однаково застосований для різних типів даних в кресленні: графічних елементів, листів або самого креслення. В якості додаткової інформації можуть використовуватися дані різних типів.
 
Як це працює і як застосовується на практиці, дивіться під катом.
 
 
 

Додавання власних властивостей графічних об'єктів

Для роботи з власними даними об'єктів використовується властивість
CustomProperties
, доступне для всіх нащадків класу
McPropertySource
, якими, зокрема, є всі графічні примітиви в базі даних (екземпляри класу
McDbEntity
). Властивість дозволяє додавати і читати дані у вигляді пар ключ-значення:
 
 
entity.DbEntity.CustomProperties["Property"] = Value;

Як значення властивостей можуть використовуватися прості типи, а також масиви простих типів. На практиці можна додавати властивості будь-яких типів, використовуючи сериализацию об'єктів для запису даних у байтовий масив. Наступний приклад демонструє приклад збереження словника даних як значення власного властивості
MyCustomProperty
:
 
 
MemoryStream ms = new MemoryStream();
BinaryFormatter formatter = new BinaryFormatter();
Dictionary<String, Object> MyOptions = new Dictionary<String, Object>();
MyOptions.Add("param1", 10);
MyOptions.Add("param2", "Value");
try
{
  formatter.Serialize(ms, MyOptions);
}
catch (SerializationException e)
{
  Console.WriteLine("Failed to serialize. Reason: " + e.Message);
}
Byte[] binary = ms.GetBuffer();
entity.DbEntity.CustomProperties["MyCustomProperty"] = binary;

Читання «складних» даних відбувається також у два етапи: отримання байтового масиву і подальша десеріалізацію.
CustomProperties
завжди повертає вміст масивів у вигляді List:
 
 
List<Byte> loadedBinary = entity.DbEntity.CustomProperties["MyCustomProperty "] as List<Byte>;
if (loadedBinary != null)
{
  ms = new MemoryStream(loadedBinary.ToArray());
  formatter = new BinaryFormatter();
  MyOptions = formatter.Deserialize(ms) as Dictionary<String, Object>;
  int val = (int)MyOptions["param1"];
  String str = MyOptions["param2"] as String;
} 

Розглянемо застосування даного методу на конкретному прикладі. Нехай. Dwg-файл містить схему водопостачання, де трубопроводи гарячої та холодної води представлені за допомогою полилиний. Додамо до окремих полилиниям опис, який буде містити інформацію про призначення трубопроводу і діаметр труби:
 
[Pipe type] = Cold Water
[Pipe diameter] = 20
 
Зареєструємо команду, яка здійснюватиме користувальницький вибір об'єкта полілінії і додавання до нього пари ключ / значення:
 
 
[CommandMethod("WriteCustomProperties", CommandFlags.NoCheck | CommandFlags.NoPrefix)]
static public void writeCold50()
{
  McObjectId objId = McObjectManager.SelectObject("Select a polyline entity to write additional data to: ");
  if (objId.GetObject().IsKindOf(DbPolyline.TypeID))
  {
    McEntity ent = objId.GetObject();
    ent.DbEntity.CustomProperties["Pipe type"] = "Cold water";
    ent.DbEntity.CustomProperties["Pipe diameter"] = 50.0;        
  }
  else
  {
    MessageBox.Show("No polyline entity selected");
  }
}

Також, для всіх нащадків класу
McPropertySource
можна отримати всі доступні властивості певного типу (Custom, Object, User тощо), використовуючи метод
GetProperties()
. Наступна команда отримує список всіх custom-властивостей для обраного на кресленні примітиву і виводить їх назви на екран.
 
 
[CommandMethod("GetCustomProperties", CommandFlags.NoCheck | CommandFlags.NoPrefix)]
static public void getCustomProperties()
  {
    McObjectId objId = McObjectManager.SelectObject("Select an entity to get its custom property list: ");
    if (objId.IsNull)
    {
      MessageBox.Show("No entity selected");
      return;
    }
      
    String propertyString = null;
    List<McProperty> customPropertyNames = new List<McProperty>();
    McEntity ent = objId.GetObject();
    customPropertyNames = ent.DbEntity.GetProperties(McProperties.PropertyType.Custom).GetProps();
    foreach (McProperty property in customPropertyNames)
    {
      propertyString = propertyString + property.Name + ";\n";
    }
    
   MessageBox.Show(propertyString, "Custom property list");
 }

 

Збереження неграфічні інформації для документа

MultiCAD.NET дозволяє зберігати неграфічні інформацію не тільки для примітивів, але також для всього документа і окремих листів і блоків (піддокументів). Клас
McDocument
також успадковує функціональність
McPropertySource
, а отже, можна використовувати все те ж властивість
CustomProperties
для завдання власних даних для документів різного рівня:
 
 
[CommandMethod("WriteCustomPropertiesToDoc", CommandFlags.NoCheck | CommandFlags.NoPrefix)]
static public void writeCustomPropertiesToDoc()
{
  McDocument currentLayout = McDocumentsManager.GetActiveSheet();
  currentLayout.CustomProperties["Layout Property 1"] = "Value";
  
  McDocument currentDocument = McDocumentsManager.GetActiveDoc();
  currentDocument.CustomProperties["Document Property 1"] = "Value";
}

Подивимося, як це працює на конкретному прикладі. В одній з минулих статей ми розповідали про створення користувацьких примітивів за допомогою MultiCAD.NET і мали справу з примітивом TextInBox, що представляє собою текст в прямокутній рамці:
 
 image
 
Використовуючи власні властивості документа, можна задати параметри і настройки цього документа. Наприклад, в даному випадку, установки кольору для рамки і текстового рядка для всіх примітивів TextInBox, присутніх у поточному документі:
 
 
McDocument currentDocument = McDocumentsManager.GetActiveDoc();
currentDocument.CustomProperties["BoxColor"] = "Blue";
currentDocument.CustomProperties["TextColor"] = "Green";

Перепишемо функцію
OnDraw()
з прикладу , що відповідає за малювання користувальницького примітиву, таким чином, щоб колір елементів читався з встановлених властивостей документа:
 
 
public override void OnDraw(GeometryBuilder dc)
{
  dc.Clear();
  dc.Color = Color.FromName(currentDocument.CustomProperties["BoxColor"] as String);
  dc.DrawPolyline(new Point3d[] { _pnt1, new Point3d(_pnt.X, _pnt2.Y, 0), 
                                  _pnt2, new Point3d(_pnt2.X, _pnt.Y, 0), 
                                  _pnt1});
  dc.TextHeight = 2.5 * DbEntity.Scale;	
  dc.Color = Color.FromName(currentDocument.CustomProperties["TextColor"] as String);
  dc.DrawMText(new Point3d((_pnt2.X + _pnt.X) / 2.0, (_pnt2.Y + _pnt.Y) / 2.0, 0), 
               Vector3d.XAxis, Text, HorizTextAlign.Center, VertTextAlign.Center);
}

Таким чином, всі додаються примітиви TextInBox відображаються у відповідність із заданими властивостями поточного документа.
    
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.