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

Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > C# Разбивка чертежа на "Модель - Лист".

C# Разбивка чертежа на "Модель - Лист".

Ответ
Поиск в этой теме
Непрочитано 23.12.2013, 16:49 #1
C# Разбивка чертежа на "Модель - Лист".
Sfinks7s1
 
VB, C++, C#, Java
 
Санкт-Петербург
Регистрация: 19.04.2013
Сообщений: 48

Возник вопрос с "разбивкой" чертежа на "Модель - Лист" с сохранением результата в соответствующих файлах.

Плагин отрабатывает, "разбивка" и сохранение в файлы происходит, но при попытке открытия такого файла происходит вылет из AutoCAD.

Показывает следующую ошибку:
http://forum.dwg.ru/attachment.php?a...1&d=1387802478

При этом после выполнения восстановления этих файлов средствами AutoCAD видно, что разбивка корректна, лишние листы из чертежей убираются.

Код:
[Выделить все]
[CommandMethod("ExportLayout")]
        public void ExportLayout()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor editor = doc.Editor;
            
            try
            {
                foreach (string lytName in GetLayoutNames(db))
                {
                   CopyLayout(doc.Name, lytName);
                }
            }
            catch (System.Exception ex)
            {
                editor.WriteMessage("\n Exception caught: " + ex);
            }
        }
        
public void CopyLayout(string docPathname, string layoutName)
        {
            string tmpPathname = Path.Combine(Path.GetTempPath(), Path.GetTempFileName() + ".dwg");
            string expDocPathname = Path.Combine("D:\\_LAYOUT\\", layoutName + ".dwg");
            File.Copy(docPathname, tmpPathname, true);

            Database db = new Database(false, true);
            using (db)
            {
                try
                {
                    db.ReadDwgFile(tmpPathname, System.IO.FileShare.ReadWrite, false, "");
                }
                catch (System.Exception ex)
                {
                    return;
                }
                try
                {
                    using (Transaction tr = db.TransactionManager.StartTransaction())
                    {
                        //LayoutManager.Current.CurrentLayout = layoutName;
                        Layout lyt;
                        DBDictionary lytDct = (DBDictionary)tr.GetObject(db.LayoutDictionaryId, OpenMode.ForRead);
                        foreach (DBDictionaryEntry dictEntry in lytDct)
                        {
                            if (dictEntry.Key != "Model" && dictEntry.Key != layoutName)
                            {
                                lyt = (Layout)tr.GetObject(dictEntry.Value, OpenMode.ForWrite);
                                //if (!lyt.ModelType)
                                lyt.Erase();
                            }
                        }
                        db.CloseInput(true);
                        db.SaveAs(expDocPathname, true, DwgVersion.Current, db.SecurityParameters);
                        tr.Commit();
                    }
                }
                catch (System.Exception ex)
                {
                    return;
                }
                File.Delete(tmpPathname); 
            }
        }
Пробовал запускать команду с разными флагами: (CommandFlags.Modal | CommandFlags.Session)
В чём моя ошибка? Может я как-то не так произвожу сохранение?

Изображения
Тип файла: jpg Error.jpg (21.8 Кб, 590 просмотров)

Просмотров: 7590
 
Непрочитано 23.12.2013, 17:25
#2
maratovich


 
Регистрация: 12.07.2009
г. Самара
Сообщений: 2,481
Отправить сообщение для maratovich с помощью Skype™


Цитата:
Сообщение от Sfinks7s1 Посмотреть сообщение
Возник вопрос с "разбивкой" чертежа на "Модель - Лист"
Это как? И где тогда чертеж если его бить и на Модель и на Лист ?
__________________
Вопрос : Где находится Тургай ? Ответ : Между Парагваем и Уругваем.....
maratovich вне форума  
 
Автор темы   Непрочитано 23.12.2013, 17:42
#3
Sfinks7s1

VB, C++, C#, Java
 
Регистрация: 19.04.2013
Санкт-Петербург
Сообщений: 48
Отправить сообщение для Sfinks7s1 с помощью Skype™


Алгоритм следующий:
Основной чертёж с несколькими листами дублируется в некотором каталоге (temp) в количестве экземпляров = количеству листов(layout).
Каждый экземпляр именуется в соответствии с именем layout'a который в нём останется, из экземпляров удаляются "лишние" листы, которые не соответствуют имени файла-экземпляра, т.о. должны остаться файлы, которые содержат только модель и 1 лист. Имя файла = имени единственного листа.
После всех манипуляций экземпляры из temp сохраняются в каталоге "D:\Layouts" и удаляются из temp.
Основной чертёж открыт в AutoCAD, его разбивка происходит без открывания экземпляров в AutoCAD т.е. "фоном".
Вот читается база экземпляра чертежа...
Код:
[Выделить все]
db.ReadDwgFile(tmpPathname, System.IO.FileShare.ReadWrite, false, "");

Последний раз редактировалось Sfinks7s1, 23.12.2013 в 17:50.
Sfinks7s1 вне форума  
 
Непрочитано 23.12.2013, 17:46
#4
Do$

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


Я выполняю копирование объектов листа по этому примеру: http://adndevblog.typepad.com/autoca...w-drawing.html
Переписать на C# несложно. У меня работает нормально.
__________________
Толковый выбор приходит с опытом, а к нему приводит выбор бестолковый. (The Mechanic)
Do$ вне форума  
 
Автор темы   Непрочитано 23.12.2013, 18:03
#5
Sfinks7s1

VB, C++, C#, Java
 
Регистрация: 19.04.2013
Санкт-Петербург
Сообщений: 48
Отправить сообщение для Sfinks7s1 с помощью Skype™


Цитата:
Сообщение от Do$ Посмотреть сообщение
Я выполняю копирование объектов листа по этому примеру: http://adndevblog.typepad.com/autoca...w-drawing.html
Переписать на C# несложно. У меня работает нормально.
Попробую Ваш вариант переписать..
Но всё же, например данный код работает нормально, но здесь для обработки каждый экземпляр открывается в AutoCAD...
При этом работает на файлах с 30 - 40 листами и всё бы ничего, но это время и ресурсы компа. Т.е. на слабом компе такой скрипт теоретически может привести к зависанию, по этому и было принято решение переписать так, чтобы обработка происходила в "фоновом" режиме.

Код:
[Выделить все]
public void CopyLayout(string docPathname, string layoutName)
        {
            string tmpPathname = Path.Combine(Path.GetTempPath(), Path.GetTempFileName() + ".dwg");
            
            string expDocPathname = Path.Combine("D:\\_LAYOUT\\", layoutName + ".dwg");

            File.Copy(docPathname, tmpPathname, true);

            Document doc = Application.DocumentManager.Open(tmpPathname, false);
            Application.DocumentManager.MdiActiveDocument = doc;
            Database db = doc.Database;
            Editor editor = doc.Editor;
            try
            {
                using (doc.LockDocument())
                {
                    using (Transaction tr = db.TransactionManager.StartTransaction())
                    {
                        LayoutManager.Current.CurrentLayout = layoutName;
                        DBDictionary lytDct = (DBDictionary)tr.GetObject(db.LayoutDictionaryId, OpenMode.ForRead);
                        foreach (DBDictionaryEntry dictEntry in lytDct)
                        {
                            if (dictEntry.Key != "Model" && dictEntry.Key != layoutName)
                            {
                                Layout lyt = (Layout)tr.GetObject(dictEntry.Value, OpenMode.ForWrite);
                                //if (!lyt.ModelType)
                                lyt.Erase();
                            }
                        }
                        tr.Commit();
                        editor.Regen();
                    }
                    db.SaveAs(expDocPathname, true, DwgVersion.Current, db.SecurityParameters);
                }
            }
            catch (System.Exception ex)
            {
                editor.WriteMessage("\n Exception caught: " + ex);
            }
            File.Delete(tmpPathname);
            doc.CloseAndDiscard();
        }
Sfinks7s1 вне форума  
 
Непрочитано 23.12.2013, 19:56
#6
Do$

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


А... Семен-Семеныч... Я понял идею: делаем копию файла, из этой копии удаляем лишние листы, а потом эту копию сохраняем отдельным чертежом. Да, копирование листа тут не нужно.
P.S. Хотя, можно и с копированием листа. 100% быстрее будет.
__________________
Толковый выбор приходит с опытом, а к нему приводит выбор бестолковый. (The Mechanic)
Do$ вне форума  
 
Непрочитано 23.12.2013, 19:59
#7
maratovich


 
Регистрация: 12.07.2009
г. Самара
Сообщений: 2,481
Отправить сообщение для maratovich с помощью Skype™


Цитата:
Сообщение от Do$ Посмотреть сообщение
Я понял идею: делаем копию файла, из этой копии удаляем лишние листы, а потом эту копию сохраняем отдельным чертежом
Остался единственный вопрос - зачем это всё? Чтобы машина меньше грузилась при работе ?
__________________
Вопрос : Где находится Тургай ? Ответ : Между Парагваем и Уругваем.....
maratovich вне форума  
 
Автор темы   Непрочитано 23.12.2013, 20:47
#8
Sfinks7s1

VB, C++, C#, Java
 
Регистрация: 19.04.2013
Санкт-Петербург
Сообщений: 48
Отправить сообщение для Sfinks7s1 с помощью Skype™


Переписал Ваш пример на C#

Код:
[Выделить все]
[CommandMethod("copyLayout")]
        public void copyLayoutToNewDwg()
        {
            Layout layout = new Layout();
            string layoutNameInCurDwg = "Layout1";
            LayoutManager lytMgr = default(LayoutManager);

            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;

            ObjectId layoutId = default(ObjectId);
            Database db = Application.DocumentManager.MdiActiveDocument.Database;
            Database newDb = new Database(true, false);

            using (Transaction tr = newDb.TransactionManager.StartTransaction())
            {
                HostApplicationServices.WorkingDatabase = newDb;
                LayoutManager newLytMgr = LayoutManager.Current;
                ObjectId newLayoutId = newLytMgr.CreateLayout("newLayout");
                Layout newLayout = (Layout)tr.GetObject(newLayoutId, OpenMode.ForWrite);

                //Make the original database the working database
                HostApplicationServices.WorkingDatabase = db;

                using (Transaction tr2 = db.TransactionManager.StartTransaction())
                {
                    // Get the dictionary of the original database
                    DBDictionary lytDict = (DBDictionary)tr2.GetObject(db.LayoutDictionaryId, OpenMode.ForRead);

                    //Make sure the layout existes in the original database
                    if (!lytDict.Contains(layoutNameInCurDwg))
                    {
                        ed.WriteMessage("Layout named \"Layout1\" does not exist in current dwg");
                        return;
                    }

                    //Get the layout in the original database
                    lytMgr = LayoutManager.Current;
                    layoutId = lytMgr.GetLayoutId(layoutNameInCurDwg);
                    layout = (Layout)tr2.GetObject(layoutId, OpenMode.ForRead);
                    newLayout.CopyFrom(layout);

                    //Get the block table record of the existing layout
                    BlockTableRecord blkTableRec = default(BlockTableRecord);
                    blkTableRec = (BlockTableRecord)tr2.GetObject(layout.BlockTableRecordId, OpenMode.ForRead);

                    //Get the object ids of the objects in the existing block table record
                    ObjectIdCollection objIdCol = new ObjectIdCollection();
                    foreach (ObjectId objId in blkTableRec)
                    {
                        objIdCol.Add(objId);
                    }

                    // Clone the objects to the new layout
                    IdMapping idMap = new IdMapping();
                    newDb.WblockCloneObjects(objIdCol, newLayout.BlockTableRecordId, idMap, DuplicateRecordCloning.MangleName, false);
                    tr2.Commit();
                }
                tr.Commit();
                newDb.SaveAs("D:\\newLayout.dwg", DwgVersion.Newest);
            }
        }

Работает нормально.


Свой вопрос решил, реализовал так:

Код:
[Выделить все]
 [CommandMethod("ExportLayout")]
        public void ExportLayout()
        {
            
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor editor = doc.Editor;
            
            try
            {
                foreach (string lytName in GetLayoutNames(db))
                {
                    
                        CopyLayout(doc.Name, lytName);
                }
                HostApplicationServices.WorkingDatabase = db;
                Application.DocumentManager.MdiActiveDocument = doc;
            }
            catch (System.Exception ex)
            {
                editor.WriteMessage("\n Exception caught: " + ex);
            }
        }

public void CopyLayout(string docPathname, string layoutName)
        {
            //var editor = Application.DocumentManager.MdiActiveDocument.Editor;
            try
            {
                string tmpPathname = Path.Combine("D:\\_LAYOUT\\", layoutName + ".dwg");
                File.Copy(docPathname, tmpPathname, true);
                Database dbX = new Database(false, true);

                dbX.ReadDwgFile(tmpPathname, System.IO.FileShare.ReadWrite, true, "");

                HostApplicationServices.WorkingDatabase = dbX;

                using (Transaction trX = dbX.TransactionManager.StartTransaction())
                {
                    LayoutManager.Current.CurrentLayout = layoutName;
                    //editor.WriteMessage(layoutName);
                    DBDictionary lytDct = (DBDictionary)trX.GetObject(dbX.LayoutDictionaryId, OpenMode.ForWrite);
                    foreach (DBDictionaryEntry dictEntry in lytDct)
                    {
                        Layout lyt = (Layout)trX.GetObject(dictEntry.Value, OpenMode.ForWrite);
                        
                        if (!lyt.ModelType && dictEntry.Key != layoutName)
                        {
                            lyt.Erase();
                        }
                    }
                    dbX.SaveAs(tmpPathname, DwgVersion.AC1027);

                    trX.Commit();
                }
            }
            catch(Autodesk.AutoCAD.Runtime.Exception ex)
            {
                return;
            }
        }
Проблема была в
Код:
[Выделить все]
HostApplicationServices.WorkingDatabase = dbX;
т.к. нужно учитывать с какой именно базой мы работаем в текущий момент времени.

Код отрабатывает даже на больших чертежах, правда всё равно ждать приходится. Видимо придётся так оставить или уже разбивать на потоки или через BackgroundWorkers...

----- добавлено через ~8 мин. -----
Цитата:
Сообщение от maratovich Посмотреть сообщение
Остался единственный вопрос - зачем это всё? Чтобы машина меньше грузилась при работе ?
Разбивка в целом нужна более для архивного хранения, т.к. с точки зрения архива более корректно не только основной файл с кучей листов хранить, но и отдельно каждый лист. Да и заказчику бывает требуется отправлять только определённые листы. В любом случае данный функционал сокращает время на "разбивку".
Sfinks7s1 вне форума  
 
Непрочитано 23.12.2013, 22:34
#9
Do$

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


Цитата:
Сообщение от Sfinks7s1 Посмотреть сообщение
Код отрабатывает даже на больших чертежах, правда всё равно ждать приходится.
Я думаю, что если в переписанный на C# код по копированию листа в новый чертеж добавить копирование всех объектов модели, то значительно быстрее получится, чем создавать копию чертежа а потом ее модифицировать. Друге дело, что создаваться новый чертеж будет на основе шаблона и этот шаблон должен соответствовать чертежу-донору.
__________________
Толковый выбор приходит с опытом, а к нему приводит выбор бестолковый. (The Mechanic)
Do$ вне форума  
 
Автор темы   Непрочитано 23.12.2013, 22:52
#10
Sfinks7s1

VB, C++, C#, Java
 
Регистрация: 19.04.2013
Санкт-Петербург
Сообщений: 48
Отправить сообщение для Sfinks7s1 с помощью Skype™


Цитата:
Сообщение от Do$ Посмотреть сообщение
Я думаю, что если в переписанный на C# код по копированию листа в новый чертеж добавить копирование всех объектов модели, то значительно быстрее получится, чем создавать копию чертежа а потом ее модифицировать. Друге дело, что создаваться новый чертеж будет на основе шаблона и этот шаблон должен соответствовать чертежу-донору.
Я тоже об этом думал, но вряд-ли это что-то ускорит, т.к. копирование всей модели в новый файл + копирование 1 листа из файла-донора + загрузка нужного шаблона (опять-таки, кто должен определять, какой шаблон актуальный? Пользователь?) тоже немало времени займёт, а вероятность не очевидных ошибок в процессе работы скрипта повышается.
Шаблон... У нас например активно используется функционал AutoCAD Architecture, множество настраиваемых стилей и блоков, многие сотрудники разработанный шаблон ещё и "под себя" подгоняют. По этому копирование базового чертежа, а затем удаление "лишних" листов с каждого экземпляра в моём случае более универсально. Для удобства хранения и передачи заказчику (а-то столько порой мусора в модели....), а также сокращения объёма файлов думаю дальше опционально добавить возможность удаления графики, которая не входит во вьюпорты на актуальном листе..
Дальше думаю надо в сторону многопоточности смотреть или выносить выполнение "тяжёлого" функционала на сервер...

Последний раз редактировалось Sfinks7s1, 23.12.2013 в 23:02.
Sfinks7s1 вне форума  
 
Непрочитано 24.12.2013, 10:05
#11
Do$

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


Насколько я знаю, многопоточность AutoCAD системы не поддерживают.
__________________
Толковый выбор приходит с опытом, а к нему приводит выбор бестолковый. (The Mechanic)
Do$ вне форума  
 
Непрочитано 24.12.2013, 10:13
#12
Дима_

Продуман
 
Регистрация: 22.02.2007
Питер
Сообщений: 2,840


Насчет многопоточности - на данном этапе если только запускать несколько автокадов, а вариант имеющий практический смысл - несколько консольных.
__________________
Когда в руках молоток все вокруг кажется гвоздями.
Дима_ вне форума  
 
Автор темы   Непрочитано 24.12.2013, 13:37
#13
Sfinks7s1

VB, C++, C#, Java
 
Регистрация: 19.04.2013
Санкт-Петербург
Сообщений: 48
Отправить сообщение для Sfinks7s1 с помощью Skype™


Цитата:
Сообщение от Дима_ Посмотреть сообщение
Насчет многопоточности - на данном этапе если только запускать несколько автокадов, а вариант имеющий практический смысл - несколько консольных.
Сама платформа AutoCAD потоконебезопасна, о чём можно судить и из данной статьи:
https://sites.google.com/site/bushma...nost-i-autocad

но есть ещё возможности Async\Await и BackgroundWorker, которые стоит хотя бы попробовать.
В общем попробую, вдруг чего и получится. О результатах отпишусь.
Sfinks7s1 вне форума  
 
Непрочитано 24.12.2013, 15:43
#14
Дима_

Продуман
 
Регистрация: 22.02.2007
Питер
Сообщений: 2,840


Цитата:
Сообщение от Sfinks7s1 Посмотреть сообщение
Сама платформа AutoCAD потоконебезопасна, о чём можно судить и из данной статьи:
https://sites.google.com/site/bushma...nost-i-autocad
По моему там ровно наоборот написанно...
Цитата:
Сообщение от Sfinks7s1 Посмотреть сообщение
но есть ещё возможности Async\Await и BackgroundWorke
Да хоть вверх ногами - если система не расчитанна на одновременное обращение - то только целиковыми транзакциями, с блокировкой всех остальных...
__________________
Когда в руках молоток все вокруг кажется гвоздями.
Дима_ вне форума  
 
Непрочитано 24.12.2013, 16:01
#15
Александр Ривилис

программист, рыцарь ObjectARX
 
Регистрация: 09.05.2005
Киев
Сообщений: 2,408
Отправить сообщение для Александр Ривилис с помощью Skype™


http://adndevblog.typepad.com/autoca...rocessing.html
Александр Ривилис вне форума  
Ответ
Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > C# Разбивка чертежа на "Модель - Лист".

Размещение рекламы


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Почему при вставке чертежа в Word меняются пропорции чертежа? МишаИнженер AutoCAD 9 28.11.2014 15:31
Hp laserjet 5035 MFP смещение чертежа на формате A3 при печати из Autocad 2011 и 2013 merdoc2003 AutoCAD 6 18.04.2013 23:59
Несвойственные Автокаду вещи Vova AutoCAD 49 01.02.2012 19:33
Копирование файла одного чертежа в директорию текущего чертежа в автокаде... CAHTEXHuK Программирование 3 23.06.2010 00:23
Максимальная подготовка DXF файла для SCAD. (Разбивка готового чертежа на элементы указанной длины) Juss_00 AutoCAD 2 09.12.2008 17:35