Сообщество программистов Autodesk в СНГ

ADN Club => AutoCAD .NET API => Тема начата: Atomohod от 08-12-2019, 19:54:30

Название: Исключить из сериализации содержимое блока
Отправлено: Atomohod от 08-12-2019, 19:54:30
Здравствуйте!
Как исключить из сериализации содержимое BlockReference с учетом того, что их несколько для каждого блока? Написал такой код, но он все равно достает полилинии из вставок блока.
Код - C# [Выбрать]
  1.  public class PolylineSerializer
  2.     {
  3.         [CommandMethod("2SerializePolylines")]
  4.         public void SerializePolylines()
  5.         {
  6.             //--------------------------------------------------------------------Mandatory variables
  7.             Document doc = Application.DocumentManager.MdiActiveDocument;
  8.             Database db = doc.Database;
  9.             Editor ed = doc.Editor;
  10.             Transaction tr = db.TransactionManager.StartTransaction();
  11.             //--------------------------------------------------------------------Mandatory variables
  12.             List < Polyline > polylines = new List < Polyline >();
  13.             using ( tr )
  14.             {
  15.                 BlockTable bt = (BlockTable) tr.GetObject(db.BlockTableId, OpenMode.ForWrite);
  16.                 BlockTableRecord mainBtr = (BlockTableRecord) tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
  17.                 List < SerializablePolyline > serializablePolylines = new List < SerializablePolyline >();
  18.  
  19.                 foreach ( ObjectId btrId in bt )
  20.                 {
  21.                     BlockTableRecord btr = (BlockTableRecord) tr.GetObject(btrId, OpenMode.ForWrite);
  22.  
  23.                     foreach ( ObjectId id in btr )
  24.                     {
  25.                         if ( id.ObjectClass.IsDerivedFrom(RXObject.GetClass(typeof(BlockReference))) )
  26.                         {
  27.                             continue;
  28.                         }
  29.  
  30.                         Entity ent = (Entity) tr.GetObject(id, OpenMode.ForWrite, false, true);
  31.  
  32.                         if ( (ent != null) && (ent is Polyline) )
  33.                         {
  34.                             polylines.Add((Polyline) ent);
  35.                         }
  36.                     }
  37.                 }
  38.  
  39.                 Vertex vertex;
  40.  
  41.                 foreach ( var pline in polylines )
  42.                 {
  43.                     var plHandle = pline.Handle.Value;
  44.                     SerializablePolyline sp = new SerializablePolyline(plHandle, new List < Vertex >(), pline.Linetype, pline.Closed);
  45.                     for ( int i = 0; i < pline.NumberOfVertices; i++ )
  46.                     {
  47.                         vertex = new Vertex(pline.GetPoint2dAt(i).X, pline.GetPoint2dAt(i).Y, pline.GetBulgeAt(i));
  48.                         sp.VerticesCollection.Add(vertex);
  49.                     }
  50.  
  51.                     serializablePolylines.Add(sp);
  52.                 }
  53.  
  54.                 var currentDate = DateTime.Now.ToLongDateString();
  55.                 AutocadSerializer.PolylineToJson(serializablePolylines, $"D:\\{currentDate}.json");
  56.                 var list2 = AutocadSerializer.GetPolylineListFromJson($"D:\\{currentDate}.json");
  57.  
  58.                 for ( int i = 0; i < list2.Count; i++ )
  59.                 {
  60.                     SerializablePolyline item = list2[ i ];
  61.                     Polyline polyline = new Polyline();
  62.                     polyline.SetDatabaseDefaults();
  63.                     for ( int j = 0; j < item.VerticesCollection.Count; j++ )
  64.                     {
  65.                         polyline.AddVertexAt(j, new Point2d(item.VerticesCollection[ j ].X, item.VerticesCollection[ j ].Y), item.VerticesCollection[ j ].Bulge, 0, 0);
  66.                     }
  67.  
  68.                     polyline.LineWeight = LineWeight.LineWeight060;
  69.                     polyline.Layer = "0";
  70.                     polyline.ColorIndex = 10;
  71.                     polyline.Closed = item.Contour;
  72.                     try
  73.                     {
  74.                         polyline.Linetype = item.Linetype;
  75.                     }
  76.                     catch ( System.Exception ex )
  77.                     {
  78.                         //Application.ShowAlertDialog("The following exception was caught:\n" + ex.Message);
  79.                     }
  80.                     finally
  81.                     {
  82.                         polyline.Linetype = "ByLayer";
  83.                     }
  84.  
  85.                     mainBtr.AppendEntity(polyline);
  86.                     tr.AddNewlyCreatedDBObject(polyline, true);
  87.                 }
  88.  
  89.                 tr.Commit();
  90.             }
  91.         }
  92.  
  93.         public static Point2dCollection VerticesToCollection(Polyline polyline)
  94.         {
  95.             Point2dCollection vertices = new Point2dCollection();
  96.             for ( int i = 0; i < polyline.NumberOfVertices; i++ )
  97.             {
  98.                 vertices.Add(polyline.GetPoint2dAt(i));
  99.             }
  100.  
  101.             return vertices;
  102.         }
  103.  
  104.     }
Название: Re: Исключить из сериализации содержимое блока
Отправлено: Александр Ривилис от 08-12-2019, 20:06:58
Как исключить из сериализации содержимое BlockReference с учетом того, что их несколько для каждого блока?
У BlockReference нет содержимого (если не считать атрибутов). Содержимое есть у BlockTableRecord (в том числе, могут быть и Polyline)
P.S.: Если не модифицируешь объект ни в коем случае не открывай его OpenMode.ForWrite - только OpenMode.ForRead.
Название: Re: Исключить из сериализации содержимое блока
Отправлено: Atomohod от 08-12-2019, 20:30:53
У BlockReference нет содержимого (если не считать атрибутов). Содержимое есть у BlockTableRecord (в том числе, могут быть и Polyline)
Можно мне пояснить один момент - существует определение блока, то есть BlockTableRecord с содержащимися в нем полилиниями. Далее на основе определения создаются вставки блока то есть BlockReference, получается, что внутри них не создаются свои полилинии? Тупой вопрос, но все же - что за полилинии мы видим во вставках, они же как-то содержатся в базе чертежа?
Название: Re: Исключить из сериализации содержимое блока
Отправлено: Александр Ривилис от 08-12-2019, 20:32:08
Тупой вопрос, но все же - что за полилинии мы видим во вставках, они же как-то содержатся в базе чертежа?
Мы видим те полилинии, которые в BlockTableRecord, на которую ссылается BlockReference.
Название: Re: Исключить из сериализации содержимое блока
Отправлено: Александр Ривилис от 08-12-2019, 20:43:13
А в чем вообще смысл задачи?
Название: Re: Исключить из сериализации содержимое блока
Отправлено: Atomohod от 08-12-2019, 20:49:01
Надо сериализовать полилинии не входящие в блоки для того, чтобы загрузить json в нашу самописную систему контроля разработки чертежа - то есть наблюдать, что происходит в чертеже каждый день, иметь возможность восстановить графику на определенный момент времени и дать пользователю возможность визуального сравнения изменений по сравнению с текущим чертежом и десериализованным из json. Похожая вещь появилась в Автокаде последних версий, но у нас только 2015 поэтому пишем сами. Это вкратце.
Название: Re: Исключить из сериализации содержимое блока
Отправлено: Atomohod от 08-12-2019, 20:53:19
Мы видим те полилинии, которые в BlockTableRecord, на которую ссылается BlockReference.
То есть handle, например, у этих линий для всех BlockReference одинаковые и мы видим линии внутри вставок. но они не хранятся внутри чертежа, создаются "на лету" лишь для визуального отображения?
Название: Re: Исключить из сериализации содержимое блока
Отправлено: Александр Ривилис от 08-12-2019, 20:54:58
Надо сериализовать полилинии не входящие в блоки
Но ведь это глупость, так как в этом случае
иметь возможность восстановить графику на определенный момент времени
не получится. Представьте себе ситуацию, если чертеж состоит только из блоков. Значит графики никакой не будет вообще.
Но если даже делать так, как по твоей постановке, то не нужно лазить во все BlockTableRecord. Достаточно входить только в те BlockTableRecord, у которых свойство IsLayout == true.
Название: Re: Исключить из сериализации содержимое блока
Отправлено: Atomohod от 08-12-2019, 20:57:35
IsLayout == true.
А почему только Layout? Если наоборот - нужно только то, что в пространстве модели?
Название: Re: Исключить из сериализации содержимое блока
Отправлено: Александр Ривилис от 08-12-2019, 20:57:45
То есть handle, например, у этих линий для всех BlockReference одинаковые и мы видим линии внутри вставок. но они не хранятся внутри чертежа, создаются "на лету" лишь для визуального отображения?
Ничего на лету не создаётся. Они уже все сидят в BlockTableRecord. Для отображения они лишь масштабируются и переносятся в соответствии с масштабными коэффициентами блока и точкой встави блока.
Название: Re: Исключить из сериализации содержимое блока
Отправлено: Александр Ривилис от 08-12-2019, 20:58:50
IsLayout == true.
А почему только Layout? Если наоборот - нужно только то, что в пространстве модели?
Потому что у BlockTableRecord пространства модели свойство IsLayout тоже true.
Название: Re: Исключить из сериализации содержимое блока
Отправлено: Atomohod от 08-12-2019, 20:59:34
не получится. Представьте себе ситуацию, если чертеж состоит только из блоков. Значит графики никакой не будет вообще.
Чертеж рисуем сами, блоки там как раз стороннее оборудование и оно из базы поставщика и никогда не меняется. Наблюдение за ним не требуется
Название: Re: Исключить из сериализации содержимое блока
Отправлено: Александр Ривилис от 08-12-2019, 21:00:31
Наблюдение за ним не требуется
И даже их расположение в чертеже???
P.S.: И конечно у вас никто не использует копирование через буфер обмена, которое приводит к появлению блоков вида A$XXXXXXXX в чертеже??? Не верю...
Название: Re: Исключить из сериализации содержимое блока
Отправлено: Atomohod от 08-12-2019, 21:03:35
И даже их расположение в чертеже???
Я чуть-чуть непродумал- положение блока в целом (Position базовой точки) интересует, его содержимое совсем нет.
Название: Re: Исключить из сериализации содержимое блока
Отправлено: Александр Ривилис от 08-12-2019, 21:04:56
И даже их расположение в чертеже???
Я чуть-чуть непродумал- положение блока в целом (Position базовой точки) интересует, его содержимое совсем нет.
Что-то мне подсказывает, что это далеко не единственное "непродуманное" в этой задаче.
Название: Re: Исключить из сериализации содержимое блока
Отправлено: Привалов Дмитрий от 09-12-2019, 07:33:10
Надо сериализовать полилинии не входящие в блоки для того, чтобы загрузить json в нашу самописную систему контроля разработки чертежа - то есть наблюдать, что происходит в чертеже каждый день, иметь возможность восстановить графику на определенный момент времени и дать пользователю возможность визуального сравнения изменений по сравнению с текущим чертежом и десериализованным из json. Похожая вещь появилась в Автокаде последних версий, но у нас только 2015 поэтому пишем сами. Это вкратце.

Что-то мне подсказывает, что это далеко не единственное "непродуманное" в этой задаче.
Поддерживаю.

1. Atomohod, я бы не рассчитывал, что пользователи используют только полилинии и блоки. Потребности могут измениться через год и сломают всю систему.
2. Может тебе все хранить в родном формате dwg? Версии можешь сохранять/восстанавливать например через git, останется продумать отображение отличий.
Название: Re: Исключить из сериализации содержимое блока
Отправлено: Дмитрий Загорулькин от 09-12-2019, 13:24:32
Похожая вещь появилась в Автокаде последних версий, но у нас только 2015 поэтому пишем сами.
Не совсем так. В AutoCAD последних версий эта вещь перекочевала внутрь. А до этого - была в виде отдельного приложения DWG Compare. Сейчас в Apps можно найти только для 2016-2019: https://apps.autodesk.com/ACD/ru/Detail/Index?id=1050435430275763742&appLang=en&os=Win32_64. Но, думаю, если сильно постараться, то можно будет найти в интернете и для версии 2015, т.к. само приложение ещё под версию 2012-2013 писалось, судя по этому: https://thecadgeek.com/blog/drawing-compare/.
Название: Re: Исключить из сериализации содержимое блока
Отправлено: Привалов Дмитрий от 09-12-2019, 13:39:23
А до этого - была в виде отдельного приложения DWG Compare
Существует еще возможность сравнения через Design Review, но файлы необходимо экспоритровать в DWF.
Название: Re: Исключить из сериализации содержимое блока
Отправлено: Atomohod от 09-12-2019, 21:32:24
все хранить в родном формате dwg? Версии можешь сохранять/восстанавливать например через git, останется продумать отображение отличий.
А кто мне их будет туда коммитить? Поставить каждому пользователю git и заставить его коммитить что-то с достаточно высокой частотой нереально - основной контингент конторы это тетеньки и дедушки от 50 и старше. Кроме того для json есть возможность чисто зрительно увидеть что менялось в сериализованном файле, а dwg git читать не умеет.
Название: Re: Исключить из сериализации содержимое блока
Отправлено: Atomohod от 09-12-2019, 21:39:56
P.S.: И конечно у вас никто не использует копирование через буфер обмена, которое приводит к появлению блоков вида A$XXXXXXXX в чертеже??? Не верю...
А в чем подвох? Пусть даже у него и странное имя, но факт появления/удаления его в чертеже и положение базовой точки ведь можно тоже зафиксировать?
Название: Re: Исключить из сериализации содержимое блока
Отправлено: Александр Ривилис от 09-12-2019, 23:09:12
А в чем подвох?
Подвох том, что в нём могут быть полилинии, которые нарисовали выши сотрудники, а вы решили, что содержимое этого блока вас не интересует. Т.е. вы пропустили эту графику...
Название: Re: Исключить из сериализации содержимое блока
Отправлено: Привалов Дмитрий от 10-12-2019, 00:45:22
А кто мне их будет туда коммитить? Поставить каждому пользователю git и заставить его коммитить что-то с достаточно высокой частотой нереально - основной контингент конторы это тетеньки и дедушки от 50 и старше
в json тетеньки и дедушки от 50 и старше как-то переводят, в git будет аналогично ;-)
git понимает команды, можно поставить на сервер.

Тут идея в другом, хранить в родном формате.
1. Т.к. dwg сложный формат и придумывать как хранить его объекты "по другому" сложно и на это уйдет много времени.
2. странно что из всех объектов только полилинии сохраняешь. Скорее всего нужны еще отрезки, а также подписи к линиям текст и мтекст. А по опыту, все что угодно. Т.е. задача может измениться и сильно усложниться в какой-то момент.
3. Меня смутило, что в задаче полилинии "восстанавливаются" из json, т.е. скорее всего, если полилиния была удалена, то ты ее добавляешь и handle приращивается, а при открытии старой копии dwg восстанавливается старый handle. Могут пойти расхождения и как следствие усложнения программы.