Импортировать координаты в чертёж можно на любом из существующих в nanoCAD видов API. Мы решили выбрать .NET и сравнить два близких API: классический .NET API и кросс-САПР-платформенный MultiCAD.NET API. Под катом — первая часть — импорт точек на классическом .NET API.
Дано: текстовый файл с координатами X, Y, Z точек, одна точка на строке. Координаты разделены пробелом, разделитель дробной части — точка.
Требуется: написать приложение, которое по команде IMPORTCOORDS запрашивает имя файла и импортирует найденные координаты в текущее пространство чертёжа в виде объектов DatabaseServices.DBPoint
. Координаты объектов должны импортироваться в текущую UCS чертежа.
Создание и настройка рабочего проекта
Для создания приложения нам понадобятся следующие инструменты:
- nanoCAD (версия не ниже 3.5)
- Microsoft Visual Studio 2008 (nanoCAD 3.5 — nanoCAD 5.0 поддерживают загрузку .NET-приложений, построенных на .NET Framework 3.5).
Для написания примера использовались следующие версии продуктов: MS Visual Studio 2008, nanoCAD 4.7.
Ну и, конечно же, подразумевается, что вы хотя бы немного знаете, что такое программирование и знакомы с языком C#. Если нет — сперва добро пожаловать в библиотеку MSDN.
Создаем новый проект в Visual Studio со следующими настройками:
- Project type: Visual C#
- Template: Class Library
Таким образом, наше приложение представляет собой обычную .NET-сборку (DLL), которая впоследствие будет загружена в nanoCAD.
Во вкладке References подключаем следующие библиотеки, входящие в состав комплекта nanoCAD:
- hostdbmgd.dll
- hostmgd.dll
Теперь можно смело переходить к написанию самой программы.
Структура программы
Реализацию можно разбить на следующие шаги:
- Зарегистрировать команду IMPORTCOORDS.
- Получить базу данных текущего чертежа и редактор командной строки.
- Запросить имя файла с координатами.
- Открыть файл, прочитать строки с координатами.
- Создать объекты DBPoint с отдельными координатами. Преобразовать их координаты в текущую пользовательскую систему координат.
- Добавить созданные объекты в текущее пространство чертежа (Model Space или Paper Space).
Для того, чтобы зарегистрировать команду, которая будет вызывать наше приложение в nanoCAD нужно перед определением метода, который будет вызываться по этой команде, объявить аттрибут [CommandMethod]
и указать имя команды. Обратите внимание, метод должен иметь модификатор public:
[CommandMethod("IMPORTCOORDS")] public void importCoords() { ... }
Прежде чем продолжить, хотелось бы остановиться и в двух словах рассказать, что же такое «база данных чертежа». .dwg-файл представляет собой базу данных, имеющую строгую структуру, основные элементы которой — таблицы (Symbol Tables), которые содержат все объекты чертежа. Это не только графические объекты, которые мы видим на чертеже (прямые, дуги, точки и тд.), но и множество других объектов, которые определяют содержимое и настройки чертежа. Например, таблица слоев (Layer Table) содержит в себе все слои, которые имеются на чертеже, таблица типов линий (Linetype Table) хранит все стили линий, определенные в чертеже, таблица пользовательских систем координат (UCS Table) — все системы координат, созданные пользователем для данного чертежа, и др. Таким образом, создать новый объект чертежа — значит создать соответствующий объект базы данных.
Итак, продолжаем. В первую очередь нам необходимо выбрать из всех открытых документов текущий и открыть его базу данных. Для этого мы получаем объект-менеджер всех открытых документов, и затем с его помощью и базу данных, с которой мы будем дальше работать.
DocumentCollection dm = Application.DocumentManager; Database db = dm.MdiActiveDocument.Database;
Для того, чтобы наше приложение запрашивало файл, необходимо получить объект редактора командной строки для вывода запроса и определить объект, который будет содержать в себе результат запроса:
// Получаем редактор командной строки Editor ed = dm.MdiActiveDocument.Editor; // Объект для получения результата запроса PromptFileNameResult sourceFileName; // Выводим запрос в командную строку и получаем результат sourceFileName = ed.GetFileNameForOpen("\nEnter the name of the coordinates file to be imported:"); if (sourceFileName.Status == PromptStatus.OK) { ... }
Итак, мы получили файл с координатами. Получить из него координаты довольно просто, используя C#-функционал для чтения текстовых файлов и работы со строковыми типами данных:
// Читаем файл, получаем содержимое в виде массива строк string[] lines = File.ReadAllLines(sourceFileName.StringResult); // Для каждой строки записываем массив из подстрок, разделенных пробелом (т.к по условию задачи в качестве разделителя координат выступает символ пробела). // Таким образом получаем массив из координат, только в текстовом виде, затем конвертируем их в числа типа double. string[] coord; foreach (string s in lines) { coord = s.Split(new char[] { ' ' }); double coordX = Convert.ToDouble(coord[0]); double coordY = Convert.ToDouble(coord[1]); double coordZ = Convert.ToDouble(coord[2]); }
Переходим к созданию графических примитивов (Entity). Как уже отмечалось выше, для того, чтобы создать любой объект (не только графический), который будет храниться в чертеже, его необходимо добавить в базу данных чертежа, а именно в соответствующий объект-контейнер. Так, например, все слои хранятся как записи в таблице слоев (Layer Table), которая является в этом случае для них объектом-контейнером.
Графические примитивы хранятся в базе не напрямую, а в структуре отдельных блоков, которые в свою очередь являются записями в таблице блоков (Block Table). Это очень удобно, поскольку такой механизм позволяет легко группировать объекты в именованные блоки и управлять ими, как единым целым. К слову, пространство модели и пространства листа в базе также представлены отдельными блоками. Таким образом, для графического примитива контейнером будет являться отдельный блок, который, в свою очередь, будет принадлежать родительскому объекту — таблице блоков.
Раз мы работаем с базой данных, то необходимо обеспечить ее целостность и защиту в случае, если во время выполнения программы произошла какая-то ошибка. Для этой цели применяется механизм транзакций. Транзакции объединяют в себе целый ряд операций, которые выполняются как единое целое: если что-то пошло не так, транзакция отменяется, и объекты, созданные в рамках этой транзакции не будут добавлены в документ. Если же все операции завершились успешно, то транзакция подтверждается, и объекты добавляются в базу.
Вооружившись этими знаниями, можем смело добавлять на чертеж примитивы «точка» по координатам, которые мы прочитали из файла. Обратите внимание, примитивы будут добавлены в текущее пространство чертежа.
using (Transaction tr = db.TransactionManager.StartTransaction()) { // Можно обойтись без таблицы блоков и получить блок текущего пространство чертежа прямо из объекта, представляющего базу данных BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite); string[] lines = File.ReadAllLines(sourceFileName.StringResult); string[] coord; foreach (string s in lines) { coord = s.Split(new char[] { ' ' }); double coordX = Convert.ToDouble(coord[0]); double coordY = Convert.ToDouble(coord[1]); double coordZ = Convert.ToDouble(coord[2]); DBPoint point = new DBPoint(new Point3d(coordX, coordY, coordZ)); btr.AppendEntity(point); tr.AddNewlyCreatedDBObject(point, true); } btr.Dispose(); tr.Commit(); }
Задача практически решена. Осталось выполнить одно условие: примитивы-точки должны создаваться в координатах пользовательской системы координат (UCS). Необходимо отметить, что примитивы хранятся в базе данных чертежа в мировой системе координат (WCS). Следовательно, при создании примитивов необходимо выполнить преобразование: UCS->WCS. Делается это при помощи матрицы пользовательской системы координат:
Matrix3d ucsMatrix = ed.CurrentUserCoordinateSystem;
Добавим преобразование:
{ ... point.TransformBy(ucsMatrix.Inverse()); ... }
Итак, программа полностью написана. Что же дальше?
Загрузка приложения в nanoCAD
Осталась самая приятная часть — загрузить программу в nanoCAD и любоваться результатами своей работы. Как вы помните, мы создавали рабочий проект как библиотеку классов, поэтому после успешной компиляции будет построена сборка с именем вашего проекта. Открываем nanoCAD, в командной строке пишем команду NETLOAD, выбираем из списка построенную библиотеку и загружаем. Для запуска программы просто введите имя команды IMPORTCOORDS в командной строке.
Импорт координат. Версия 2.0
Усовершенствуем первую версию приложения, добавив несколько полезных функций и элементы пользовательского интерфейса.
Если первая версия приложения «понимала» текстовый файл, в котором координаты разделены только пробелами и в качестве десятичного разделителя использовалась точка, то теперь приложение будет обладать более высоким интеллектом и сумеет «распознать» координаты, разделенные символом табуляции, пробелом или точкой с запятой. Что же касается десятичного разделителя, то в качестве него теперь может выступать как точка, так и запятая, импорт будет производиться без учета региональных настроек. По команде IMPORTCOORDS теперь будет открываться модальный диалог импорта координат, в котором пользователь может выбрать файл и указать желаемые настройки импорта координат.
Общий механизм импорта координат и создания примитивов остается практически без изменений, однако теперь это будет происходить в рамках класса формы, а задача метода-обработчика команды IMPORTCOORDS теперь сводится лишь к созданию объекта формы и выводу формы на экран в виде модального диалога:
[CommandMethod("IMPORTCOORDS")] public void importCoords() { Form form = new ImportForm(); HostMgd.ApplicationServices.Application.ShowModalDialog(form); }
После чего управление будет передано окну формы импорта координат.
Форма приложения
Форма для приложения включает в себя следующие элементы:
- Кнопка для открытия файла
- Диалог открытия файла
- Группа чекбоксов для выбора символов-разделителей координат: табуляция, пробел, точка с запятой
- Текстовое поле для предварительного просмотра разбора строк c координатами
- Кнопка для импорта координат
- Кнопка отмены
Используя эти элементы управления, пользователь теперь может указать желаемые символы-разделители, проверить результат в поле предварительного просмотра (примерно так, как это сделано в MS Excel при импорте текстового файла) и инициировать импорт координат:
Совместимость с AutoCAD
В заключение хотелось бы отметить, что приложение, написанное для nanoCAD, может быть с легкостью перекомпилировано и для работы в AutoCAD. Для этого необходимо сделать следующее:
- Во вкладке References подключить следующие библиотеки, входящие в состав ObjectARX:
- AcCoreMgd.dll
- AcDbMgd.dll
- AcMgd.dll
Добавить в код приложения директиву условной компиляции, для определения пространств имен, которые будут использоваться для компиляции под nanoCAD или AutoCAD:
#if ACAD using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Geometry; using Autodesk.AutoCAD.Runtime; using Platform = Autodesk.AutoCAD; using PlatformDb = Autodesk.AutoCAD; #else using HostMgd.ApplicationServices; using HostMgd.EditorInput; using Teigha.DatabaseServices; using Teigha.Geometry; using Teigha.Runtime; using Platform = HostMgd; using PlatformDb = Teigha; #endif
- Заменить в коде специфичные для каждой платформы пространства имен на определенные выше псевдонимы:
Platform
иPlatformDb
.
Обе версии проекта доступны здесь.
ссылка на оригинал статьи http://habrahabr.ru/company/nanosoft/blog/187498/
Добавить комментарий