Проблема с удалением размеров из ModelSpace

Автор Тема: Проблема с удалением размеров из ModelSpace  (Прочитано 7583 раз)

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

Оффлайн valtur1983Автор темы

  • ADN OPEN
  • Сообщений: 46
  • Карма: 2
Доброго вечера форумчане!

Использую метод SelectWindow для выделения всех элементов в заданной области. Почему то удаляются все элементы кроме размеров
Вот фрагмент кода который использую для удаления:



Код - C# [Выбрать]
  1. using (Transaction tr = db.TransactionManager.StartTransaction())
  2.             {
  3.                 Point3d pt1 = new Point3d(intSmeschPlanX +intShagSetkiXPlan * (intPosColumnInModel - 1),
  4.                     intSmeschPlanY - intShagSetkiYPlan * (intPosRowInModel - 1), 0);
  5.                 Point3d pt2 = new Point3d(intSmeschPlanX + intShagSetkiXPlan + intShagSetkiXPlan * (intPosColumnInModel - 1),
  6.                     intSmeschPlanY + intShagSetkiYPlan - intShagSetkiYPlan * (intPosRowInModel - 1), 0);
  7.  
  8.  
  9.                 PromptSelectionResult psel = ed.SelectWindow(pt1, pt2);
  10.  
  11.                 if (psel.Status != PromptStatus.OK)
  12.                 {
  13.                     ed.WriteMessage("\nError!\n");
  14.                     return;
  15.                 }
  16.  
  17.                 foreach (ObjectId idsel in psel.Value.GetObjectIds())
  18.                 {
  19.                     DBObject dbobj = tr.GetObject(idsel, OpenMode.ForRead) as DBObject;
  20.                     dbobj.UpgradeOpen();
  21.                     dbobj.Erase();
  22.                 }
  23.                 tr.Commit();
  24.             }
  25.  

В чем проблема?

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Почему то удаляются все элементы кроме размеров
А размеры полностью помещаются в рамку? Они попадают в набор выбора?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн valtur1983Автор темы

  • ADN OPEN
  • Сообщений: 46
  • Карма: 2
Почему то удаляются все элементы кроме размеров
А размеры полностью помещаются в рамку? Они попадают в набор выбора?

Я не знаю попадают ли они в набор, но в заданных координатах они точно присутствуют.

Я же их не вручную выделяю. SelectCrossingWindow тоже не дает результата

Макрос выполняется в Autocad 2018

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
valtur1983,
Ну и по стилю работы с AutoCAD. Это плохо:
Код - C# [Выбрать]
  1.                 foreach (ObjectId idsel in psel.Value.GetObjectIds())
  2.                 {
  3.                     DBObject dbobj = tr.GetObject(idsel, OpenMode.ForRead) as DBObject;
  4.                     dbobj.UpgradeOpen();
  5.                     dbobj.Erase();
  6.                 }
Это лучше:
Код - C# [Выбрать]
  1.                 foreach (ObjectId idsel in psel.Value.GetObjectIds())
  2.                 {
  3.                     DBObject dbobj = tr.GetObject(idsel, OpenMode.ForWrite) as DBObject;
  4.                     if (dbobj != null) dbobj.Erase();
  5.                 }
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Я не знаю попадают ли они в набор, но в заданных координатах они точно присутствуют.
Проверь попадают ли они в набор.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн valtur1983Автор темы

  • ADN OPEN
  • Сообщений: 46
  • Карма: 2
valtur1983,
Ну и по стилю работы с AutoCAD. Это плохо:
Код - C# [Выбрать]
  1.                 foreach (ObjectId idsel in psel.Value.GetObjectIds())
  2.                 {
  3.                     DBObject dbobj = tr.GetObject(idsel, OpenMode.ForRead) as DBObject;
  4.                     dbobj.UpgradeOpen();
  5.                     dbobj.Erase();
  6.                 }
Это лучше:
Код - C# [Выбрать]
  1.                 foreach (ObjectId idsel in psel.Value.GetObjectIds())
  2.                 {
  3.                     DBObject dbobj = tr.GetObject(idsel, OpenMode.ForWrite) as DBObject;
  4.                     if (dbobj != null) dbobj.Erase();
  5.                 }

За нюансы такие Спасибо! Код пишется под конкретную задачу для себя, и начал работать плотно только месяц назад, так что очень многих проверок нет, да и решения кочуют из метода в метод.

Оффлайн valtur1983Автор темы

  • ADN OPEN
  • Сообщений: 46
  • Карма: 2
Я не знаю попадают ли они в набор, но в заданных координатах они точно присутствуют.
Проверь попадают ли они в набор.

А как мне через код проверить что размеры попадают в выбор. Вручную через отладку это проблематично.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
А как мне через код проверить что размеры попадают в выбор
Да хоть так:
Код - C# [Выбрать]
  1. RXClass cls =  RXObject.GetClass(typeof(Dimension));
  2. foreach (ObjectId idsel in psel.Value.GetObjectIds())
  3.                 {
  4.                     DBObject dbobj = tr.GetObject(idsel, OpenMode.ForWrite) as DBObject;
  5.                     if (dbobj != null) {
  6.                           if (dbobj.GetRXClass().IsDerivedFrom(cls) {
  7.                                 ed.WriteMessage("\nDimension {0}", dbobj.ObjectId);
  8.                           }
  9.                           dbobj.Erase();
  10.                     }
  11.                 }
Код не проверял совсем. Могут быть описки. Написал только ради того, чтобы показать идею.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн valtur1983Автор темы

  • ADN OPEN
  • Сообщений: 46
  • Карма: 2
Я не знаю попадают ли они в набор, но в заданных координатах они точно присутствуют.
Проверь попадают ли они в набор.

А как мне через код проверить что размеры попадают в выбор. Вручную через отладку это проблематично.

Не попадают в выборку размеры. Хотя они нормально вставились из другого чертежа так же как и другие элементы

Оффлайн valtur1983Автор темы

  • ADN OPEN
  • Сообщений: 46
  • Карма: 2
Что то у меня, после изменений перестали вставляться размеры из другого чертежа
Вот код:
Код - C# [Выбрать]
  1. using (Transaction extTr = OpenDb.TransactionManager.StartTransaction())
  2.                     {
  3.  
  4.                         BlockTable extBt = (BlockTable)extTr.GetObject(OpenDb.BlockTableId, OpenMode.ForRead);
  5.                         BlockTableRecord extModelSpace = (BlockTableRecord)extTr.GetObject(extBt[BlockTableRecord.ModelSpace], OpenMode.ForRead);
  6.  
  7.                         foreach (ObjectId obj in extModelSpace)
  8.                             if (!obj.IsEffectivelyErased && !obj.IsErased && obj.IsValid)
  9.                             {
  10.                                 Entity entity = (Entity)extTr.GetObject(obj, OpenMode.ForWrite);
  11.                                 Vector3d vec = new Vector3d(12000, 594, 0);
  12.                                 entity.TransformBy(Matrix3d.Displacement(vec));
  13.                                 ids.Add(obj);
  14.  
  15.                             }
  16.  
  17.                         IdMapping iMap = new IdMapping();
  18.                         OpenDb.WblockCloneObjects(ids, destBt[BlockTableRecord.ModelSpace], iMap, DuplicateRecordCloning.Ignore, false);
  19.  
  20.                         extTr.Commit();
  21.  
  22.                     }
  23.  

Раньше все работало нормально

Может быть проблема именно в вставке?

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
valtur1983,
Не знаю почему у тебя проблемы именно с размерами. Что я точно вижу, так это то, что ты пытаешься смещать оригинальные объекты, а не копии в новом чертеже. А это ошибка. Кроме того WblockCloneObjects следует выполнять вне транзакции. Ты вот сдвинул оригинальные объекты, а транзакция еще не закрыта.
P.S.: Новые копии объектов ты можешь получить из IdMapping после WblockCloneObjects. Открываешь их на запись и затем смещаешь. Транзакция должна быть из новой базы.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн valtur1983Автор темы

  • ADN OPEN
  • Сообщений: 46
  • Карма: 2
valtur1983,
Не знаю почему у тебя проблемы именно с размерами. Что я точно вижу, так это то, что ты пытаешься смещать оригинальные объекты, а не копии в новом чертеже. А это ошибка. Кроме того WblockCloneObjects следует выполнять вне транзакции. Ты вот сдвинул оригинальные объекты, а транзакция еще не закрыта.
P.S.: Новые копии объектов ты можешь получить из IdMapping после WblockCloneObjects. Открываешь их на запись и затем смещаешь. Транзакция должна быть из новой базы.

Подскажите, в IdMapping, IdPair, куда копать, чтобы получить вставляемые объекты.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Подскажите, в IdMapping, IdPair, куда копать, чтобы получить вставляемые объекты.
idPair.Key - исходный объект, idPair.Value - копия объекта.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн valtur1983Автор темы

  • ADN OPEN
  • Сообщений: 46
  • Карма: 2
При оригинальном коде все работает нормально. Изменения по смещению работают только в элементах которые вставляются, не затрагивая исходный код. Думал что это нормально.

Переделал в такой код вставки со смещением исходных элементов:

Код - C# [Выбрать]
  1. using (Transaction tr = destdb.TransactionManager.StartTransaction())
  2.             {
  3.                 BlockTable destBt = (BlockTable)tr.GetObject(destdb.BlockTableId, OpenMode.ForRead);
  4.                 ObjectIdCollection ids = new ObjectIdCollection();
  5.                 IdMapping iMap = new IdMapping();
  6.  
  7.                 using (Database OpenDb = new Database(false, true))
  8.                 {
  9.                     OpenDb.ReadDwgFile(strNameFile,
  10.                         System.IO.FileShare.ReadWrite, true, "");
  11.  
  12.  
  13.                     using (Transaction extTr = OpenDb.TransactionManager.StartTransaction())
  14.                     {
  15.  
  16.                         BlockTable extBt = (BlockTable)extTr.GetObject(OpenDb.BlockTableId, OpenMode.ForRead);
  17.                         BlockTableRecord extModelSpace = (BlockTableRecord)extTr.GetObject(extBt[BlockTableRecord.ModelSpace], OpenMode.ForRead);
  18.  
  19.                         foreach (ObjectId obj in extModelSpace)
  20.                             if (!obj.IsEffectivelyErased && !obj.IsErased && obj.IsValid)
  21.                             {
  22.                                 DBObject entity = extTr.GetObject(obj, OpenMode.ForWrite);
  23.                                 ids.Add(obj);
  24.  
  25.                             }
  26.  
  27.                         extTr.Commit();
  28.                         OpenDb.WblockCloneObjects(ids, destBt[BlockTableRecord.ModelSpace], iMap, DuplicateRecordCloning.Ignore, false);
  29.  
  30.                     }
  31.                 }
  32.  
  33.                 foreach (IdPair obj in iMap)
  34.                 {
  35.                     DBObject dbobj = tr.GetObject(obj.Value, OpenMode.ForWrite);
  36.                     if (dbobj != null)
  37.                     {
  38.                         Entity ent;
  39.                         if ((ent = (Entity)dbobj) != null)
  40.                         {
  41.                             Vector3d vec = new Vector3d(12000, 594, 0);
  42.                             ent.TransformBy(Matrix3d.Displacement(vec));
  43.                         }
  44.  
  45.                     }
  46.                 }
  47.                  tr.Commit();
  48.             }
  49.  

Но он выдает ошибку в следующих строках:
1) Иногда

Код - C# [Выбрать]
  1.  if ((ent = (Entity)dbobj) != null)
  2.  

Ошибка: System.InvalidCastException: "Не удалось привести тип объекта "Autodesk.AutoCAD.DatabaseServices.DBDictionary" к типу "Autodesk.AutoCAD.DatabaseServices.Entity"."

2) Иногда здесь

Код - C# [Выбрать]
  1. ent.TransformBy(Matrix3d.Displacement(vec));
  2.  

Ошибка: transformby entity eNotApplicable


Оффлайн valtur1983Автор темы

  • ADN OPEN
  • Сообщений: 46
  • Карма: 2
Исходный файл , откуда вставляются элементы, состоит из блоков, размеров, линий, полилиний и.т.п (т.е. планировки с сетями)

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
valtur1983,
Похоже ты пока не совсем понимаешь, что делаешь.
1. Что за вложенные транзакции?
2. При копировании копируются не только выбранные примитивы, но и связанные с ними объекты (слои, описания блоков, типы линий и т.д. и т.п). Ты должен проверять obj.Value на Entity и трансформировать только их.
3. Entity - это наследник DBObject. Поэтому преобразование (Entity)dbobj может не выполняться для слоёв, описаний блоков и т.д. Нужно проверять (dbobj as Entity) на null
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн valtur1983Автор темы

  • ADN OPEN
  • Сообщений: 46
  • Карма: 2
valtur1983,
Похоже ты пока не совсем понимаешь, что делаешь.
1. Что за вложенные транзакции?
2. При копировании копируются не только выбранные примитивы, но и связанные с ними объекты (слои, описания блоков, типы линий и т.д. и т.п). Ты должен проверять obj.Value на Entity и трансформировать только их.
3. Entity - это наследник DBObject. Поэтому преобразование (Entity)dbobj может не выполняться для слоёв, описаний блоков и т.д. Нужно проверять (dbobj as Entity) на null

1. С транзакциями конечна беда. Я их всюду использую. В данном контексте я вставленную транзакцию использую для чтения элементов из исходного чертежа, которая вложена в транзакцию вставки в исходный чертеж. Подскажите где можно внятно про эту тему почитать. Я думал, что можно использовать вложенные транзакции и ничего в этом плохого нет.

2 и 3 замечания я так понял связаны. Не пойму в чем отличия проверки obj.Value на Entity и (dbobj as Entity)!=null

Посмотрите пожалуйста код:
Код - C# [Выбрать]
  1. foreach (IdPair obj in iMap)
  2.                 {
  3.                     ObjectId obj1 = obj.Value;
  4.                     DBObject dbobj = tr.GetObject(obj.Value, OpenMode.ForWrite);
  5.                     if (dbobj != null)
  6.                     {
  7.                         Entity ent;
  8.                         if ((dbobj as Entity) != null)
  9.                         {
  10.                             ent = (Entity)dbobj;
  11.                             Vector3d vec = new Vector3d(12000, 594, 0);
  12.                             ent.TransformBy(Matrix3d.Displacement(vec));
  13.                         }
  14.  
  15.                     }
  16.  
  17.                 }
  18.  
  19.  

Ошибка в
Код - C# [Выбрать]
  1. ent.TransformBy(Matrix3d.Displacement(vec));
  2.  

Autodesk.AutoCAD.Runtime.Exception: "eNotApplicable"

obj.Value Name=="AcDbBlockBegin"

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Подскажите где можно внятно про эту тему почитать.
Нигде. Только опыт.
Я думал, что можно использовать вложенные транзакции и ничего в этом плохого нет.
Ничего хорошего в этом нет. Их следует использовать только в крайнем случае, когда без этого не обойтись.
Не пойму в чем отличия проверки obj.Value на Entity и (dbobj as Entity)!=null
(Entity)dbobj вызывает исключение, если dbobj не Entity или его наследник. А (dbobj as Entity) не вызывает исключения, а становится равным null если dbobj не Entity или его наследник.
Ошибка в
Код - C# [Выбрать]

    ent.TransformBy(Matrix3d.Displacement(vec));
     


Autodesk.AutoCAD.Runtime.Exception: "eNotApplicable"

obj.Value Name=="AcDbBlockBegin"
Ага. Ну тут всё понятно. В данном случае ent не в ModelSpace, а в описании блока. Короче говоря тебе нужно проверять, что ent.OwnerId == destBt[BlockTableRecord.ModelSpace]
Лучше всего заранее сохранить это значение:
Код - C# [Выбрать]
  1. ObjectId idModel = destBt[BlockTableRecord.ModelSpace];
и тогда сравнение
Код - C# [Выбрать]
  1. if (ent.OwnerId == idModel) {
  2.  ent.TransformBy(Matrix3d.Displacement(vec));
  3. }
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн valtur1983Автор темы

  • ADN OPEN
  • Сообщений: 46
  • Карма: 2
Спасибо, все заработало и вставка и удаление

Глюк с удалением размеров был в том что процедура удаления элементов (в том числе и размеров) запускалась внутри транзакции вставки в чертеж. Как только я вынес процедуру за транзакцию все стало работать нормально. Хотя не пойму почему проблема коснулась именно размеров, а все остальное нормально удалилось с чертежа.

Буду впредь внимательнее к транзакциям подходить.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Хотя не пойму почему проблема коснулась именно размеров, а все остальное нормально удалилось с чертежа.
Сложный вопрос. Размеры - это сложные примитивы, которые порождают описание связанных с ним блоков. При удалении размеров должны удаляться и описания блоков. Если таблица блоков открыта для чтения, то это может мешать удалению блоков. Вот одна из возможных причин.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение