Как стать автором
Обновить

AutoCAD Architecture: First project

Время на прочтение7 мин
Количество просмотров12K
В линейке продуктов от Autodesk, кроме базового AutoCAD, существует много специализированных продуктов, оптимизированных под различные сферы проектирования. Одним из таких продуктов является AutoCAD Architecture (ACA). Аналогично AutoCAD, для AutoCAD Architecture возможно написание плагинов на .NET. Кроме библиотек от Autodesk для работы с объектами AutoCAD Architecture можно пользоваться C++ библиотекой Teigha Architecture от Open Design Alliance, которая позволяет загружать, отрисовывать и манипулировать архитектурными объектами.

Я хочу написать серию tutorial-ов, демонстрирующих работу с архитектурными объектами с помощью Autodesk .NET API и Teigha Architecture. Начнем с самых азов: соберем и заставим работать упражнение “your first project” из документации к ACA, а затем немного расширим его для использования объектов Autodesk.Aec.Arch.DatabaseServices.Wall.

image

Для опытных программистов описание покажется длинным, но я считаю что первые шажки стоит описывать детально, чтобы исключить разночтения и дать возможность человеку без особых проблем запустить хотябы простейшее приложение. При дальнейшей работе проблем с ACA .NET API и так будет предостаточно.

Предыдущая моя статья, описывающая основы ACA, пролетела как фанера над Ярославлем попала в Geektimes и доступна здесь: Введение в AutoCAD Architecture. Из нее можно получить поверхностное представление о том что такое AutoCAD Architecture, какие объекты в нем реализованы и в чем их особенности.

Писать плагин я буду в VS2010 а проверять работу в ACA 2013 x64. Разные версии ACA могут требовать разные версии .NET Framework, кроме этого плагин, построенный для x32 не подгрузится ACA x64.

Шаг 1


Создаем проект Visual C# class library под названием AcaSample1 как показано на скриншоте. Версия .NET Framework у нас будет 4.

image

Шаг 2


Документация советует сразу добавить в references acmgd.dll и acdbmgd.dll с необходимыми для примера классами из ACA. Эти файлы лежат в корне папки, куда установлен ACA. У меня это C:\Program Files\Autodesk\AutoCAD 2013
Добавим нужные библиотеки как показано на скриншотах ( References -> Add reference -> вкладка browse )

image

image

Если все сделано правильно, в списке References появятся две новые библиотеки:

image

Далее, выделяем два добавленных референса, нажимаем на них правой кнопкой, идем в свойства и ставим им свойсво copy local в false. Это сделать необходимо, чтобы в будущем избежать трудноотлавливаемых глюков. Вот что пишет документация по этому поводу:

Setting Copy Local to False instructs Microsoft Visual Studio to not include the referenced DLL in the build output for the project. If the referenced DLL is copied to the build output folder, it can cause unexpected results when you load your assembly file in AutoCAD.


image

Шаг 3


Попробуем создать код команды так, как это предлагает документация. Сэмпл из ACA почему-то оперирует объектом MText а не архитектурными примитивами. Пройдем по примеру.
Добавляем директивы using:

using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;


Добавляем код:

[assembly: CommandClass(typeof(AcaSample1.Class1))]
namespace AcaSample1
{
    public class Class1
    {
        [CommandMethod("AdskGreeting")]
        public void AdskGreeting()
        {
            // Get the current document and database, and start a transaction       
            Document acDoc = Application.DocumentManager.MdiActiveDocument;
            Database acCurDb = acDoc.Database;            // Starts a new transaction with the Transaction Manager 
            using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
            {
                // Open the Block table record for read  //            
                BlockTable acBlkTbl;
                acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead) as BlockTable;
                // Open the Block table record Model space for write              
                BlockTableRecord acBlkTblRec;
                acBlkTblRec = acTrans.GetObject(acBlkTbl[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
                /* Creates a new MText object and assigns it a location,           
                 * text value and text style */
                MText objText = new MText();                // Specify the insertion point of the MText object
                objText.Location = new Autodesk.AutoCAD.Geometry.Point3d(2, 2, 0);                // Set the text string for the MText object            
                objText.Contents = "Greetings, Welcome to the AutoCAD .NET Developer's Guide";                // Set the text style for the MText object   
                objText.TextStyleId = acCurDb.Textstyle;                // Appends the new MText object to model space   
                acBlkTblRec.AppendEntity(objText);                // Appends to new MText object to the active transaction   
                acTrans.AddNewlyCreatedDBObject(objText, true);                // Saves the changes to the database and closes the transaction        
                acTrans.Commit();
            }
        }
    }
}


Здесь AdskGreeting это имя команды. Впоследствии это имя нужно будет вводить в командной строке ACA, чтобы исполнить код функции AdskGreeting()
Пытаемся сбилдить… ну конечно, оно не билдится :)

image

Причина в том, что нам не хватает референсов, в которых определены CommandClass, CommandMethod и тд – accoremgd.dll
Эта библиотека тоже лежит в корне папки куда установлен ACA. Добавляем этот референс и ставим ему copy local в false:

image

Пробуем запустить билд: библиотека должна построиться без ошибок. В результате у нас получилась AcaSample1.dll

Шаг 4


Теперь нам надо обратить внимание на платформу. Например, дефолтная платформа в 2010 студии Debug \ AnyCPU, а у меня стоит Win 7 x64 и ACA x64. При попытке загрузить эту длл ACA x64 выдаст ошибку. Поэтому мне надо поменять целевую платформу:

image

Перестроим проект. На этом этапе должна получиться библиотека AcaSample1.dll в AcaSample1\AcaSample1\bin\x64\Debug
Документация еще советует проверить target framework
On the Applications tab, Target Framework drop-down list, select .NET Framework 4.0

но мы его выставляли на первом шаге при создании проекта.

image

Шаг 5


Пробуем загрузить наш плагин в ACA и выполнить команду. Открываем ACA 2013 и вводим в командной строке netload ( командную строку можно вызвать комбинацией ctrl + 9, если она скрыта ). Откроется диалоговое окно для выбора плагина ( правда если переменная FILEDIA у вас стоит в 0, то окно не откроется, а будет предложено ввести пусть до dll плагина в командной строке ). Идем в папку с солюшеном, ищем AcaSample1.dll ( у меня это AcaSample1\bin\x64\Debug ) и нажимаем open:

image

Если ошибок небыло, ACA промолчит. Набираем команду AdskGreeting. Если ошибок небыло, автокад опять промолчит, и, скорее всего, на экране ничего не изменится. Это потому что текст слишком мал или выходит из области, на которую направлена камера. Чтобы его увидеть используем команду zoom extents из панели (вкладка view):

image

В результате должны увидеть такое:

image

Ок. С небольшими дополнениями удалось построить и запустить базовый пример из документации к AutoCAD Architecture.

Шаг 6


Теперь попробуем сделать команду, которая использует собственно объекты ACA. Например, стены. Для этого заменим весь код примера на следующее (код кривоват, использовать только для пробы):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;

using Autodesk.Aec.Arch.DatabaseServices;

[assembly: CommandClass(typeof(AcaSample2_Walls.Class1))]
namespace AcaSample2_Walls
{
    public class Class1
    {
        [CommandMethod("CreateHouse")]
        public static void CreateHouse()
        {
            Document acDoc = Application.DocumentManager.MdiActiveDocument;
            Database acCurDb = acDoc.Database;

            acDoc.Editor.WriteMessage("\n CreateHouse command");

            using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
            {
                // Open the Block table record for read 
                BlockTableRecord acModelSpace = GetModelSpaceRecord(acCurDb, acTrans, OpenMode.ForWrite);

                AddWallToModelSpace(new Point3d(0, 0, 0), new Point3d(5000, 0, 0), acModelSpace, acTrans);
                AddWallToModelSpace(new Point3d(5000, 0, 0), new Point3d(5000, 5000, 0), acModelSpace, acTrans);
                AddWallToModelSpace(new Point3d(5000, 5000, 0), new Point3d(0, 5000, 0), acModelSpace, acTrans);
                AddWallToModelSpace(new Point3d(0, 5000, 0), new Point3d(0, 0, 0), acModelSpace, acTrans);

                acTrans.Commit();
            }

            acDoc.SendStringToExecute("_-VIEW _SWISO ", true, false, false);
            acDoc.SendStringToExecute("_.zoom _all ", true, false, false);
        }


        public static BlockTableRecord GetModelSpaceRecord(Database acDb, Transaction acTrans, OpenMode om)
        {
            // Open the Block table record for read 
            BlockTable acBlkTbl;
            acBlkTbl = acTrans.GetObject(acDb.BlockTableId, OpenMode.ForRead) as BlockTable;
            // Open the Block table record Model space for read 
            BlockTableRecord acBlkTblRec;
            acBlkTblRec = acTrans.GetObject(acBlkTbl[BlockTableRecord.ModelSpace], om) as BlockTableRecord;

            return acBlkTblRec;
        }

        private static void AddWallToModelSpace(Point3d ptS, Point3d ptE, BlockTableRecord acModelSpace, Transaction acTrans)
        {
            Wall w = new Wall();
            w.Set(ptS, ptE, new Vector3d(0, 0, 1));
            w.BaseHeight = 2500;
            w.InstanceWidth = 300;

            acModelSpace.AppendEntity(w);
            acTrans.AddNewlyCreatedDBObject(w, true);
        }
    }
}


Мы написали новую команду CreateHouse, которая создает «дом» из четырех стен. В данном случае мы уже начали использовать объекты ACA, поэтому добавилась директива
using Autodesk.Aec.Arch.DatabaseServices;

Aec.Arch — это уже область архитектурных объектов.

Команды
 acDoc.SendStringToExecute("_-VIEW _SWISO ", true, false, false);
  acDoc.SendStringToExecute("_.zoom _all ", true, false, false);

поворачивают вид в изометрическую проекцию и делают вызов zoom_extents, который ранее мы делали руками в UI ACA.

Чтобы построить этот проект в references необходимо добавить библиотеки, в которых реализованы объекты ACA. В данном примере нам потребуются AecBaseMgd.dll и AecArchMgd.dll. Не забудьте также поставить поставить им свойство Copy local в false.
У меня эти библиотеки находятся в C:\Program Files\Autodesk\AutoCAD 2013\ACA\

image

Все, что начинается на Aec, относится к ACA.

image

Строим проект, подгружаем его с помощью netload в AutoCAD Architecture 2013 и выполняем команду CreateHouse. Должно получиться так:

image

Заключение


В данной статье я попробовал дать пошаговую инструкцию к первым попыткам программирования под ACA. Я знаю что тут есть похожие статьи про использование .NET API, но в данном случае мне захотелось изложить все подводящие шаги к использованию архитектурного API.

В следующих статьях я покажу как сделать ваше первое приложение с помощью Teigha Architecture, а затем перейду к разбору того, что же происходит в этих примерах: что такое dwg, что такое база данных куда мы добавляем стены, отличия архитектурных объектов от базовых примитивов автокада в плане работы с ними. Затем надеюсь рассмотреть более общие сценарии: как отрендерить архитектурные объекты в нужном представлении, как получить их геометрию для конвертации в другие форматы, как с ними работать и тд.
Теги:
Хабы:
+11
Комментарии5

Публикации

Истории

Работа

.NET разработчик
75 вакансий

Ближайшие события

Weekend Offer в AliExpress
Дата20 – 21 апреля
Время10:00 – 20:00
Место
Онлайн
Конференция «Я.Железо»
Дата18 мая
Время14:00 – 23:59
Место
МоскваОнлайн