Это шестая часть цикла про разработку плагинов для AutoCAD. В ней поговорим про поиск объектов на чертеже, а также про их изменение.
public static string disclaimer = "Автор не является профессиональным разработчиком и не обладает глубокими знаниями AutoCAD. Этот пост – просто небольшой рассказ о создании плагина.";
CopyLocal
) и подключаем уже привычные библиотеки AcMgd и AcDbMgd. Далее помещаем туда функции, создающие объекты для нашего примера.using System;
using System.Collections.Generic;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.EditorInput;
using acad = Autodesk.AutoCAD.ApplicationServices.Application;
namespace HabrPlug_SearchAndRescue
{
public class ClassMyAutoCADDLL_SearchAndRescue
{
public class Commands : IExtensionApplication
{
// используемые цвета
Autodesk.AutoCAD.Colors.Color color_Pink = Autodesk.AutoCAD.Colors.Color.FromRgb(255, 128, 255);
Autodesk.AutoCAD.Colors.Color color_Blue = Autodesk.AutoCAD.Colors.Color.FromRgb(0, 200, 255);
Autodesk.AutoCAD.Colors.Color color_LightGreen = Autodesk.AutoCAD.Colors.Color.FromRgb(128, 255, 64);
// ID слоев "layer-1" и "layer-2"
ObjectId layer_1;
ObjectId layer_2;
// создаем слои
public void createLayers()
{
// получаем текущий документ и его БД
Document acDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
Database acCurDb = acDoc.Database;
// блокируем документ
using (DocumentLock docloc = acDoc.LockDocument())
{
// начинаем транзакцию
using (Transaction tr = acCurDb.TransactionManager.StartTransaction())
{
// открываем таблицу слоев документа
LayerTable acLyrTbl = tr.GetObject(acCurDb.LayerTableId, OpenMode.ForWrite) as LayerTable;
// создаем новый слой и задаем ему имя
LayerTableRecord acLyrTblRec_1 = new LayerTableRecord();
acLyrTblRec_1.Name = "layer-1";
// заносим созданный слой в таблицу слоев, сохраняем ID созданной записи слоя
layer_1 = acLyrTbl.Add(acLyrTblRec_1);
// добавляем созданный слой в документ
tr.AddNewlyCreatedDBObject(acLyrTblRec_1, true);
// создаем новый слой и задаем ему имя
LayerTableRecord acLyrTblRec_2 = new LayerTableRecord();
acLyrTblRec_2.Name = "layer-2";
// заносим созданный слой в таблицу слоев, сохраняем ID созданной записи слоя
layer_2 = acLyrTbl.Add(acLyrTblRec_2);
// добавляем созданный слой в документ
tr.AddNewlyCreatedDBObject(acLyrTblRec_2, true);
// фиксируем транзакцию
tr.Commit();
}
}
}
// создаем определение блока "block-1"
public void createBlock_1()
{
// получаем ссылки на документ и его БД
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
// имя создаваемого блока
const string blockName = "block-1";
// начинаем транзакцию
Transaction tr = db.TransactionManager.StartTransaction();
using (tr)
{
// открываем таблицу блоков на запись
BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForWrite);
// проверяем, нет ли в таблице блока с таким именем; если есть - заканчиваем выполнение команды
if (bt.Has(blockName))
{
return;
}
// создаем новое определение блока, задаем ему имя
BlockTableRecord btr = new BlockTableRecord();
btr.Name = blockName;
// добавляем созданное определение блока в таблицу блоков и в транзакцию
bt.Add(btr);
tr.AddNewlyCreatedDBObject(btr, true);
// добавляем к блоку элементы
// создаем окружность
Circle acCircle = new Circle();
// устанавливаем параметры созданного объекта
acCircle.SetDatabaseDefaults();
acCircle.Center = Point3d.Origin;
acCircle.Radius = 25;
// добавляем созданный объект в определение блока и в транзакцию
btr.AppendEntity(acCircle);
tr.AddNewlyCreatedDBObject(acCircle, true);
// создаем линию
Line acLine = new Line(new Point3d(18, 18, 0), new Point3d(35, 35, 0));
// устанавливаем параметры созданного объекта равными параметрам по умолчанию
acLine.SetDatabaseDefaults();
// добавляем созданный объект в определение блока и в транзакцию
btr.AppendEntity(acLine);
tr.AddNewlyCreatedDBObject(acLine, true);
// создаем полилинию
Polyline acPolyline = new Polyline();
// устанавливаем параметры созданного объекта равными параметрам по умолчанию
acPolyline.SetDatabaseDefaults();
// добавляем к полилинии вершины
acPolyline.AddVertexAt(0, new Point2d(20, 35), 0, 0, 0);
acPolyline.AddVertexAt(1, new Point2d(35, 35), 0, 0, 0);
acPolyline.AddVertexAt(2, new Point2d(35, 20), 0, 0, 0);
// добавляем созданный объект в определение блока и в транзакцию
btr.AppendEntity(acPolyline);
tr.AddNewlyCreatedDBObject(acPolyline, true);
// фиксируем транзакцию
tr.Commit();
}
}
// создаем определение блока "block-2"
public void createBlock_2()
{
// получаем ссылки на документ и его БД
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
// имя создаваемого блока
const string blockName = "block-2";
// начинаем транзакцию
Transaction tr = db.TransactionManager.StartTransaction();
using (tr)
{
// открываем таблицу блоков на запись
BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForWrite);
// проверяем, нет ли в таблице блока с таким именем; если есть - заканчиваем выполнение команды
if (bt.Has(blockName))
{
return;
}
// создаем новое определение блока, задаем ему имя
BlockTableRecord btr = new BlockTableRecord();
btr.Name = blockName;
// добавляем созданное определение блока в таблицу блоков и в транзакцию
bt.Add(btr);
tr.AddNewlyCreatedDBObject(btr, true);
// добавляем к блоку элементы
// создаем окружность
Circle acCircle = new Circle();
// устанавливаем параметры созданного объекта
acCircle.SetDatabaseDefaults();
acCircle.Center = Point3d.Origin;
acCircle.Radius = 25;
// добавляем созданный объект определение блока и в транзакцию
btr.AppendEntity(acCircle);
tr.AddNewlyCreatedDBObject(acCircle, true);
// создаем первую линию
Line acLine_1 = new Line(new Point3d(0, -25, 0), new Point3d(0, -50, 0));
// устанавливаем параметры созданного объекта равными параметрам по умолчанию
acLine_1.SetDatabaseDefaults();
// добавляем созданный объект в определение блока и в транзакцию
btr.AppendEntity(acLine_1);
tr.AddNewlyCreatedDBObject(acLine_1, true);
// создаем вторую линию
Line acLine_2 = new Line(new Point3d(-7, -39, 0), new Point3d(7, -39, 0));
// устанавливаем параметры созданного объекта равными параметрам по умолчанию
acLine_2.SetDatabaseDefaults();
// добавляем созданный объект в определение блока и в транзакцию
btr.AppendEntity(acLine_2);
tr.AddNewlyCreatedDBObject(acLine_2, true);
// фиксируем транзакцию
tr.Commit();
}
}
// создаем объекты на нулевом слое
public void layer_0_createObjects()
{
// получаем текущий документ и его БД
Document doc = acad.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
// начинаем транзакцию
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// открываем таблицу блоков документа
BlockTable acBlkTbl;
acBlkTbl = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
// открываем пространство модели (Model Space) - оно является одной из записей в таблице блоков документа
BlockTableRecord ms = tr.GetObject(acBlkTbl[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
// добавляем розовую линию
Line acLine_1 = new Line(new Point3d(225, 225, 0), new Point3d(225, 175, 0));
// устанавливаем параметры созданного объекта равными параметрам по умолчанию
acLine_1.SetDatabaseDefaults();
// устанавливаем для объекта нужный слой и цвет
acLine_1.Layer = "0";
acLine_1.Color = color_Pink;
// добавляем созданный объект в пространство модели и в транзакцию
ms.AppendEntity(acLine_1);
tr.AddNewlyCreatedDBObject(acLine_1, true);
// добавляем голубую линию
Line acLine_2 = new Line(new Point3d(250, 225, 0), new Point3d(250, 175, 0));
// устанавливаем параметры созданного объекта равными параметрам по умолчанию
acLine_2.SetDatabaseDefaults();
// устанавливаем для объекта нужный слой и цвет
acLine_2.Layer = "0";
acLine_2.Color = color_Blue;
// добавляем созданный объект в пространство модели и в транзакцию
ms.AppendEntity(acLine_2);
tr.AddNewlyCreatedDBObject(acLine_2, true);
// добавляем салатовую линию
Line acLine_3 = new Line(new Point3d(275, 225, 0), new Point3d(275, 175, 0));
// устанавливаем параметры созданного объекта равными параметрам по умолчанию
acLine_3.SetDatabaseDefaults();
// устанавливаем для объекта нужный слой и цвет
acLine_3.Layer = "0";
acLine_3.Color = color_LightGreen;
// добавляем созданный объект в пространство модели и в транзакцию
ms.AppendEntity(acLine_3);
tr.AddNewlyCreatedDBObject(acLine_3, true);
// добавляем розовую полилинию
Polyline acPolyline = new Polyline();
// устанавливаем параметры созданного объекта равными параметрам по умолчанию
acPolyline.SetDatabaseDefaults();
// добавляем к полилинии вершины
acPolyline.AddVertexAt(0, new Point2d(300, 225), 0, 0, 0);
acPolyline.AddVertexAt(1, new Point2d(325, 175), 0, 0, 0);
acPolyline.AddVertexAt(2, new Point2d(350, 225), 0, 0, 0);
// устанавливаем для объекта нужный слой и цвет
acPolyline.Layer = "0";
acPolyline.Color = color_Pink;
// добавляем созданный объект в пространство модели и в транзакцию
ms.AppendEntity(acPolyline);
tr.AddNewlyCreatedDBObject(acPolyline, true);
// добавляем голубую окружность
Circle acCircle = new Circle();
// устанавливаем параметры созданного объекта
acCircle.SetDatabaseDefaults();
acCircle.Center = new Point3d(400, 200, 0);
acCircle.Radius = 25;
// устанавливаем для объекта нужный слой и цвет
acCircle.Layer = "0";
acCircle.Color = color_Blue;
// добавляем созданный объект в пространство модели и в транзакцию
ms.AppendEntity(acCircle);
tr.AddNewlyCreatedDBObject(acCircle, true);
// добавляем салатовый текст
DBText text = new DBText();
text.Position = new Point3d(450, 175, 0);
text.Height = 50;
text.TextString = "HABR!";
// устанавливаем для объекта нужный слой и цвет
text.Layer = "0";
text.Color = color_LightGreen;
// добавляем созданный объект в пространство модели и в транзакцию
ms.AppendEntity(text);
tr.AddNewlyCreatedDBObject(text, true);
// фиксируем изменения
tr.Commit();
}
}
// создаем объекты на слое "layer-1"
public void layer_1_createObjects()
{
// получаем текущий документ и его БД
Document doc = acad.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
// начинаем транзакцию
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// запоминаем текущий слой и временно меняем его на нужный нам
// (это позволит не задавать слой отдельно для каждого создаваемого объекта)
ObjectId currentLayer = db.Clayer;
db.Clayer = layer_1;
// открываем таблицу блоков документа
BlockTable acBlkTbl;
acBlkTbl = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
// открываем пространство модели (Model Space) - оно является одной из записей в таблице блоков документа
BlockTableRecord ms = tr.GetObject(acBlkTbl[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
// добавляем розовую линию
Line acLine_1 = new Line(new Point3d(225, 25, 0), new Point3d(225, -25, 0));
// устанавливаем параметры созданного объекта
acLine_1.SetDatabaseDefaults();
acLine_1.Color = color_Pink;
// добавляем созданный объект в пространство модели и в транзакцию
ms.AppendEntity(acLine_1);
tr.AddNewlyCreatedDBObject(acLine_1, true);
// добавляем голубую линию
Line acLine_2 = new Line(new Point3d(250, 25, 0), new Point3d(250, -25, 0));
// устанавливаем параметры созданного объекта
acLine_2.SetDatabaseDefaults();
acLine_2.Color = color_Blue;
// добавляем созданный объект в пространство модели и в транзакцию
ms.AppendEntity(acLine_2);
tr.AddNewlyCreatedDBObject(acLine_2, true);
// добавляем салатовую окружность
Circle acCircle = new Circle();
// устанавливаем параметры созданного объекта
acCircle.SetDatabaseDefaults();
acCircle.Center = new Point3d(300, 0, 0);
acCircle.Radius = 25;
acCircle.Color = color_LightGreen;
// добавляем созданный объект в пространство модели и в транзакцию
ms.AppendEntity(acCircle);
tr.AddNewlyCreatedDBObject(acCircle, true);
// добавляем розовый текст
DBText text = new DBText();
// устанавливаем параметры созданного объекта
text.Position = new Point3d(350, -25, 0);
text.Height = 50;
text.TextString = "HABR!";
text.Color = color_Pink;
// добавляем созданный объект в пространство модели и в транзакцию
ms.AppendEntity(text);
tr.AddNewlyCreatedDBObject(text, true);
// добавляем вхождение блока "block-1"
// открываем таблицу блоков для чтения
BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
// получаем ObjectID блока
ObjectId btrId = bt["block-1"];
// создаем новое вхождение блока, используя полученный ID определения блока
BlockReference br = new BlockReference(new Point3d(600, 0, 0), btrId);
// добавляем вхождение блока на пространство модели и в транзакцию
ms.AppendEntity(br);
tr.AddNewlyCreatedDBObject(br, true);
// возвращаем обратно старый текущий слой
db.Clayer = currentLayer;
// фиксируем изменения
tr.Commit();
}
}
// создаем объекты на слое "layer-2"
public void layer_2_createObjects()
{
// получаем текущий документ и его БД
Document doc = acad.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
// начинаем транзакцию
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// запоминаем текущий слой и временно меняем его на нужный нам
// (это позволит не задавать слой отдельно для каждого создаваемого объекта)
ObjectId currentLayer = db.Clayer;
db.Clayer = layer_2;
// открываем таблицу блоков документа
BlockTable acBlkTbl;
acBlkTbl = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
// открываем пространство модели (Model Space) - оно является одной из записей в таблице блоков документа
BlockTableRecord ms = tr.GetObject(acBlkTbl[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
// добавляем розовую линию
Line acLine_1 = new Line(new Point3d(225, -175, 0), new Point3d(225, -225, 0));
// устанавливаем параметры созданного объекта
acLine_1.SetDatabaseDefaults();
acLine_1.Color = color_Pink;
// добавляем созданный объект в пространство модели и в транзакцию
ms.AppendEntity(acLine_1);
tr.AddNewlyCreatedDBObject(acLine_1, true);
// добавляем голубую дугу
Arc acArc = new Arc(new Point3d(250, -200, 0), 25, -45 / 180.0 * Math.PI, 45 / 180.0 * Math.PI);
// устанавливаем параметры созданного объекта
acArc.SetDatabaseDefaults();
acArc.Color = color_Blue;
// добавляем созданный объект в пространство модели и в транзакцию
ms.AppendEntity(acArc);
tr.AddNewlyCreatedDBObject(acArc, true);
// добавляем салатовую окружность
Circle acCircle = new Circle();
// устанавливаем параметры созданного объекта
acCircle.SetDatabaseDefaults();
acCircle.Center = new Point3d(325, -200, 0);
acCircle.Radius = 25;
acCircle.Color = color_LightGreen;
// добавляем созданный объект в пространство модели и в транзакцию
ms.AppendEntity(acCircle);
tr.AddNewlyCreatedDBObject(acCircle, true);
// добавляем вхождение блока "block-1"
// открываем таблицу блоков для чтения
BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
// получаем ObjectID блока
ObjectId btrId = bt["block-1"];
// создаем новое вхождение блока, используя полученный ID определения блока
BlockReference br = new BlockReference(new Point3d(400, -200, 0), btrId);
// добавляем вхождение блока на пространство модели и в транзакцию
ms.AppendEntity(br);
tr.AddNewlyCreatedDBObject(br, true);
// добавляем вхождение блока "block-2"
// получаем ObjectID блока
btrId = bt["block-2"];
// создаем новое вхождение блока, используя полученный ID определения блока
br = new BlockReference(new Point3d(475, -200, 0), btrId);
// добавляем вхождение блока на пространство модели и в транзакцию
ms.AppendEntity(br);
tr.AddNewlyCreatedDBObject(br, true);
// возвращаем обратно старый текущий слой
db.Clayer = currentLayer;
// фиксируем изменения
tr.Commit();
}
}
// создаем объекты при загрузке плагина
public void Initialize()
{
createLayers();
createBlock_1();
createBlock_2();
layer_0_createObjects();
layer_1_createObjects();
layer_2_createObjects();
}
// функция Terminate() необходима, чтобы реализовать интерфейс IExtensionApplication
public void Terminate()
{
}
}
}
}
Initialize()
.Initialize()
. В идеале здесь должны находиться только layer_0_createObjects()
) принадлежность к этому слою явно указывается для каждого создаваемого объекта. Пример:acLine_1.Layer = "0";
layer_1_createObjects()
код для вставки на чертеж линии из функции layer_0_createObjects()
, забыв поменять слой на новый. Поиски ошибки и ее исправление заняли какое-то время. Осознав, что так придется делать со всеми примитивами, автор выбесился и решил все сделать другим способом.Clayer
.Clayer
базы данных текущего документа. Просмотреть это значение можно так:Document doc = acad.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
ObjectId currentLayer = db.Clayer;
Document doc = acad.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
db.Clayer = layer_1; // layer_1 - ObjectID нужного слоя
ObjectID
слоя, зная его имя:Document acDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
Database acCurDb = acDoc.Database;
using (DocumentLock docloc = acDoc.LockDocument())
{
using (Transaction tr = acCurDb.TransactionManager.StartTransaction())
{
LayerTable acLyrTbl = tr.GetObject(acCurDb.LayerTableId, OpenMode.ForWrite) as LayerTable;
ObjectId layer_objID = acLyrTbl["someLayer"]
}
}
layer_1
и layer_2
, в которые сохраняю ObjectID
слоев «layer-1» и «layer-2» при их создании. А позже, в процедурах layer_1_createObjects()
и layer_2_createObjects()
, я использую следующую конструкцию:// ...
ObjectId currentLayer = db.Clayer;
db.Clayer = layer_1;
// ...
// ДОБАВЛЯЕМ НОВЫЕ ОБЪЕКТЫ
// ...
db.Clayer = currentLayer;
// ...
Clayer
и восстанавливать его в конце функции?ModelSpace
и получение идентификаторов объектов чертежа с помощью метода Editor.SelectAll()
.ModelSpace
ModelSpace
) и получаем ссылки на все объекты внутри него. Затем приводим эти объекты к типу Entity
и обрабатываем нужные нам свойства.[CommandMethod("Habr_IterateThroughAllObjects_1")]
public void iterateThroughAllObjects()
{
// получаем текущую БД
Database db = HostApplicationServices.WorkingDatabase;
// начинаем транзакцию
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// получаем ссылку на пространство модели (ModelSpace)
BlockTableRecord ms = (BlockTableRecord)tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);
// "пробегаем" по всем объектам в пространстве модели
foreach (ObjectId id in ms)
{
// приводим каждый из них к типу Entity
Entity entity = (Entity)tr.GetObject(id, OpenMode.ForRead);
// выводим в консоль слой (entity.Layer), тип (entity.GetType().ToString()) и цвет (entity.Color) каждого объекта
acad.DocumentManager.MdiActiveDocument.Editor.WriteMessage(string.Format("\nLayer:{0}; Type:{1}; Color: {2},{3},{4}\n",
entity.Layer, entity.GetType().ToString(), entity.Color.Red.ToString(), entity.Color.Green.ToString(), entity.Color.Blue.ToString()));
}
tr.Commit();
}
}
WorkingDatabase
класса HostApplicationServices
. Оно позволяет получить БД документа, который активен (имеет фокус ввода) в настоящий момент. Еще одно новшество — метод GetBlockModelSpaceId()
класса SymbolUtilityServices
, который позволяет быстро получить ObjectId
пространства модели (ModelSpace
).// команда для итерации по объектам (подход 1)
[CommandMethod("Habr_IterateThroughAllObjects_1")]
public void iterateThroughAllObjects()
{
// получаем текущий документ и его БД
Document doc = acad.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
// начинаем транзакцию
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// получаем ссылку на пространство модели (ModelSpace)
// открываем таблицу блоков документа
BlockTable acBlkTbl = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
// открываем пространство модели (Model Space) - оно является одной из записей в таблице блоков документа
BlockTableRecord ms = tr.GetObject(acBlkTbl[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
// "пробегаем" по всем объектам в пространстве модели
foreach (ObjectId id in ms)
{
// приводим каждый из них к типу Entity
Entity entity = (Entity)tr.GetObject(id, OpenMode.ForRead);
// выводим в консоль слой (entity.Layer), тип (entity.GetType().ToString()) и цвет (entity.Color) каждого объекта
acad.DocumentManager.MdiActiveDocument.Editor.WriteMessage(string.Format("\nLayer:{0}; Type:{1}; Color: {2},{3},{4}\n",
entity.Layer, entity.GetType().ToString(), entity.Color.Red.ToString(), entity.Color.Green.ToString(), entity.Color.Blue.ToString()));
}
tr.Commit();
}
}
Entity
(чтобы можно было просматривать их свойства) и выводим в консоль данные о слое, типе и цвете очередного объекта.if (entity.GetType() == typeof(Circle))
// если условие верно - значит, это окружность
[CommandMethod("Habr_FindCircles_1")]
public void findCircles_1()
{
// получаем текущую БД
Database db = HostApplicationServices.WorkingDatabase;
// начинаем транзакцию
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// получаем ссылку на пространство модели (ModelSpace)
BlockTableRecord ms = (BlockTableRecord)tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);
// "пробегаем" по всем объектам в пространстве модели
foreach (ObjectId id in ms)
{
// приводим каждый из них к типу Entity
Entity entity = (Entity)tr.GetObject(id, OpenMode.ForRead);
// если это окружность - выводим в консоль слой, тип и цвет каждого объекта
if (entity.GetType() == typeof(Circle))
{
acad.DocumentManager.MdiActiveDocument.Editor.WriteMessage(string.Format("\nLayer:{0}; Type:{1}; Color: {2},{3},{4}\n",
entity.Layer, entity.GetType().ToString(), entity.Color.Red.ToString(), entity.Color.Green.ToString(), entity.Color.Blue.ToString()));
}
}
tr.Commit();
}
}
if (entity.GetType() == typeof(Line))
if (entity.GetType() == typeof(DBText))
if (entity.GetType() == typeof(BlockReference))
if (entity.GetType() == typeof(Circle))
if (entity.Color == Autodesk.AutoCAD.Colors.Color.FromRgb(128, 255, 64))
// команда для поиска салатовых объектов (подход 1)
[CommandMethod("Habr_FindLightGreenObjects_1")]
public void findLightGreenObjects_1()
{
// получаем текущую БД
Database db = HostApplicationServices.WorkingDatabase;
// начинаем транзакцию
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// получаем ссылку на пространство модели (ModelSpace)
BlockTableRecord ms = (BlockTableRecord)tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);
// "пробегаем" по всем объектам в пространстве модели
foreach (ObjectId id in ms)
{
// приводим каждый из них к типу Entity
Entity entity = (Entity)tr.GetObject(id, OpenMode.ForRead);
// если цвет объекта - салатовый, то выводим в консоль слой, тип и цвет каждого объекта
if (entity.Color == Autodesk.AutoCAD.Colors.Color.FromRgb(128, 255, 64))
{
acad.DocumentManager.MdiActiveDocument.Editor.WriteMessage(string.Format("\nLayer:{0}; Type:{1}; Color: {2},{3},{4}\n",
entity.Layer, entity.GetType().ToString(), entity.Color.Red.ToString(), entity.Color.Green.ToString(), entity.Color.Blue.ToString()));
}
}
tr.Commit();
}
}
if (entity.Layer == "0")
Entity test; test.
" — после этого IntelliSense высветит все доступные программисту свойства и методы. Можно пробежаться по этому списку и ознакомиться со свойствами и методами класса Entity:Entity
задает свойства, характерные для любого объекта чертежа: слой, цвет и т. п. Если требуется осуществить поиск по свойствам, специфичным для какого-то конкретного класса объектов, то необходимо вначале найти все объекты такого типа, затем выполнить приведение к этому типу и просмотреть значение нужного свойства.Entity
не содержит сведений об имени определения блока; зато эта информация есть в свойстве Name
класса BlockReference
.[CommandMethod("Habr_FindBlocks_1")]
public void findBlocks_1()
{
// получаем текущую БД
Database db = HostApplicationServices.WorkingDatabase;
// начинаем транзакцию
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// получаем ссылку на пространство модели (ModelSpace)
BlockTableRecord ms = (BlockTableRecord)tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);
// "пробегаем" по всем объектам в пространстве модели
foreach (ObjectId id in ms)
{
// приводим каждый из них к типу Entity
Entity entity = (Entity)tr.GetObject(id, OpenMode.ForRead);
// проверяем, является ли объект вхождением блока
if (entity.GetType() == typeof(BlockReference))
{
// если является - приводим его к типу BlockReference
BlockReference br = (BlockReference)entity;
// если имя соответствующего определения блока - "block-1", то выводим в консоль слой, тип и цвет каждого объекта
if (br.Name == "block-1")
{
acad.DocumentManager.MdiActiveDocument.Editor.WriteMessage(string.Format("\nLayer:{0}; Type:{1}; Color: {2},{3},{4}\n",
entity.Layer, entity.GetType().ToString(), entity.Color.Red.ToString(), entity.Color.Green.ToString(), entity.Color.Blue.ToString()));
}
}
}
tr.Commit();
}
}
Editor.SelectAll()
// команда для итерации по объектам (подход 2)
[CommandMethod("Habr_IterateThroughAllObjects_2")]
public void iterateThroughAllObjects_2()
{
// получаем БД и Editor текущего документа
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
// пытаемся получить ссылки на все объекты
// ВНИМАНИЕ! Нужно проверить работоспособность метода с замороженными и заблокированными слоями!
PromptSelectionResult selRes = ed.SelectAll();
// если произошла ошибка - сообщаем о ней
if (selRes.Status != PromptStatus.OK)
{
ed.WriteMessage("\nError!\n");
return;
}
// получаем массив ID объектов
ObjectId[] ids = selRes.Value.GetObjectIds();
// начинаем транзакцию
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// "пробегаем" по всем полученным объектам
foreach (ObjectId id in ids)
{
// приводим каждый из них к типу Entity
Entity entity = (Entity)tr.GetObject(id, OpenMode.ForRead);
// выводим в консоль слой (entity.Layer), тип (entity.GetType().ToString()) и цвет (entity.Color) каждого объекта
acad.DocumentManager.MdiActiveDocument.Editor.WriteMessage(string.Format("\nLayer:{0}; Type:{1}; Color: {2},{3},{4}\n",
entity.Layer, entity.GetType().ToString(), entity.Color.Red.ToString(), entity.Color.Green.ToString(), entity.Color.Blue.ToString()));
}
tr.Commit();
}
}
Editor.SelectAll()
. Поскольку никаких фильтров не задано, нам должны вернуться идентификаторы (ObjectID
) всех объектов на чертеже. Они записываются в переменную типа PromptSelectionResult
. На всякий случай нужно убедиться, что метод отработал корректно — для этого мы проверяем статус результата (PromptSelectionResult.Status
). Если что-то не в порядке, значение этого свойства будет отлично от PromptStatus.OK
— в этом случае мы завершаем выполнение функции.Editor.SelectAll()
отработал корректно, мы получаем идентификаторы всех объектов, возвращенных этим методом. Для этого мы используем метод PromptSelectionResult.Value.GetObjectIds()
. После этого мы просто обрабатываем все объекты в цикле — точь-в-точь как в первом разделе, когда мы обращались к ModelSpace
.Editor.SelectAll()
должен возвращать только объекты на слоях, которые НЕ являются заблокированными (locked) или замороженными (frozen). Однако в этом случае документация, похоже, привирает: Editor.SelectAll()
всегда возвращает все объекты на чертеже, вне зависимости от состояний слоев, на которых они находятся. Подробнее почитать про эту забавность можно в блоге Kean Walmsley (англ.), в AutoCAD Devblog (англ.), на форумах сообщества Autodesk (англ.).Editor.SelectAll()
, очевидно, необходимо иметь объект класса Editor
. При работе с документом, который непосредственно открыт в AutoCAD, проблем не возникнет; но использовать данный метод для обработки БД сторонних документов (не открытых в настоящий момент в AutoCAD) не получится (англ.).Editor.SelectAll()
есть возможность действовать по-другому.SelectionFilter
, а затем применяем этот фильтр в методе Editor.SelectAll()
. В результате у нас остаются только удовлетворяющие условию фильтра объекты.[CommandMethod("Habr_FindCircles_2")]
public void findCircles_2()
{
// получаем БД и Editor текущего документа
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
// создаем переменную, в которой будут содержаться данные для фильтра
TypedValue[] filterlist = new TypedValue[1];
// первый аргумент (0) указывает, что мы задаем тип объекта
// второй аргумент ("CIRCLE") - собственно тип
filterlist[0] = new TypedValue(0, "CIRCLE");
// создаем фильтр
SelectionFilter filter = new SelectionFilter(filterlist);
// пытаемся получить ссылки на объекты с учетом фильтра
// ВНИМАНИЕ! Нужно проверить работоспособность метода с замороженными и заблокированными слоями!
PromptSelectionResult selRes = ed.SelectAll(filter);
// если произошла ошибка - сообщаем о ней
if (selRes.Status != PromptStatus.OK)
{
ed.WriteMessage("\nError!\n");
return;
}
// получаем массив ID объектов
ObjectId[] ids = selRes.Value.GetObjectIds();
// начинаем транзакцию
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// "пробегаем" по всем полученным объектам
foreach (ObjectId id in ids)
{
// приводим каждый из них к типу Entity
Entity entity = (Entity)tr.GetObject(id, OpenMode.ForRead);
// выводим в консоль слой, тип и цвет каждого объекта
acad.DocumentManager.MdiActiveDocument.Editor.WriteMessage(string.Format("\nLayer:{0}; Type:{1}; Color: {2},{3},{4}\n",
entity.Layer, entity.GetType().ToString(), entity.Color.Red.ToString(), entity.Color.Green.ToString(), entity.Color.Blue.ToString()));
}
tr.Commit();
}
}
Editor.SelectAll()
может принимать на вход объект типа SelectionFilter
, который и задает фильтр. Этот фильтр инициализируется с помощью массива объектов типа TypedValue
. Конструктор TypedValue
принимает на вход два параметра:public TypedValue(int typeCode, object value);
The DXF format is a tagged data representation of all the information contained in an AutoCAD drawing file of a specific version. Tagged data means that each data element in the file is preceded by an integer number that is called a group code. A group code's value indicates what type of data element follows. It also indicates the meaning of a data element for a given object (or record) type. Virtually all user-specified information in a drawing file can be represented in DXF format. The DXF format is essentially the same when used with applications (AutoLISP and ARX). However, there are a few minor differences for some data groups.
typeCode
значение 0. Откуда оно взялось и что означает — можно посмотреть в списке (англ.)0: Text string indicating the entity type (fixed)
Autodesk.AutoCAD.DatabaseServices.DxfCode
:[Wrapper("AcDb::DxfCode")]
public enum DxfCode
{
Invalid = -9999,
XDictionary = -6,
PReactors = -5,
Operator = -4,
XDataStart = -3,
FirstEntityId = -2,
HeaderId = -2,
End = -1,
Start = 0,
XRefPath = 1,
Text = 1,
AttributeTag = 2,
ShapeName = 2,
BlockName = 2,
SymbolTableName = 2,
MlineStyleName = 2,
SymbolTableRecordName = 2,
Description = 3,
TextFontFile = 3,
AttributePrompt = 3,
LinetypeProse = 3,
DimStyleName = 3,
DimPostString = 3,
CLShapeName = 4,
DimensionAlternativePrefixSuffix = 4,
TextBigFontFile = 4,
SymbolTableRecordComments = 4,
Handle = 5,
DimensionBlock = 5,
LinetypeName = 6,
DimBlk1 = 6,
DimBlk2 = 7,
TextStyleName = 7,
LayerName = 8,
CLShapeText = 9,
XCoordinate = 10,
YCoordinate = 20,
ZCoordinate = 30,
Elevation = 38,
Thickness = 39,
TxtSize = 40,
ViewportHeight = 40,
Real = 40,
ViewWidth = 41,
TxtStyleXScale = 41,
ViewportAspect = 41,
TxtStylePSize = 42,
ViewLensLength = 42,
ViewFrontClip = 43,
ViewBackClip = 44,
ShapeXOffset = 44,
ViewHeight = 45,
ShapeYOffset = 45,
ShapeScale = 46,
PixelScale = 47,
LinetypeScale = 48,
DashLength = 49,
MlineOffset = 49,
LinetypeElement = 49,
ViewportSnapAngle = 50,
Angle = 50,
ViewportTwist = 51,
Visibility = 60,
LayerLinetype = 61,
Color = 62,
HasSubentities = 66,
ViewportVisibility = 67,
ViewportActive = 68,
ViewportNumber = 69,
Int16 = 70,
ViewMode = 71,
TxtStyleFlags = 71,
RegAppFlags = 71,
CircleSides = 72,
LinetypeAlign = 72,
ViewportZoom = 73,
LinetypePdc = 73,
ViewportIcon = 74,
ViewportSnap = 75,
ViewportGrid = 76,
ViewportSnapStyle = 77,
ViewportSnapPair = 78,
Int32 = 90,
Subclass = 100,
EmbeddedObjectStart = 101,
ControlString = 102,
DimVarHandle = 105,
UcsOrg = 110,
UcsOrientationX = 111,
UcsOrientationY = 112,
XReal = 140,
ViewBrightness = 141,
ViewContrast = 142,
Int64 = 160,
XInt16 = 170,
NormalX = 210,
NormalY = 220,
NormalZ = 230,
XXInt16 = 270,
Int8 = 280,
RenderMode = 281,
Bool = 290,
XTextString = 300,
BinaryChunk = 310,
ArbitraryHandle = 320,
SoftPointerId = 330,
HardPointerId = 340,
SoftOwnershipId = 350,
HardOwnershipId = 360,
LineWeight = 370,
PlotStyleNameType = 380,
PlotStyleNameId = 390,
ExtendedInt16 = 400,
LayoutName = 410,
ColorRgb = 420,
ColorName = 430,
Alpha = 440,
GradientObjType = 450,
GradientPatType = 451,
GradientTintType = 452,
GradientColCount = 453,
GradientAngle = 460,
GradientShift = 461,
GradientTintVal = 462,
GradientColVal = 463,
GradientName = 470,
Comment = 999,
ExtendedDataAsciiString = 1000,
ExtendedDataRegAppName = 1001,
ExtendedDataControlString = 1002,
ExtendedDataLayerName = 1003,
ExtendedDataBinaryChunk = 1004,
ExtendedDataHandle = 1005,
ExtendedDataXCoordinate = 1010,
ExtendedDataWorldXCoordinate = 1011,
ExtendedDataWorldXDisp = 1012,
ExtendedDataWorldXDir = 1013,
ExtendedDataYCoordinate = 1020,
ExtendedDataWorldYCoordinate = 1021,
ExtendedDataWorldYDisp = 1022,
ExtendedDataWorldYDir = 1023,
ExtendedDataZCoordinate = 1030,
ExtendedDataWorldZCoordinate = 1031,
ExtendedDataWorldZDisp = 1032,
ExtendedDataWorldZDir = 1033,
ExtendedDataReal = 1040,
ExtendedDataDist = 1041,
ExtendedDataScale = 1042,
ExtendedDataInteger16 = 1070,
ExtendedDataInteger32 = 1071,
}
filterlist[0] = new TypedValue(0, "CIRCLE");
filterlist[0] = new TypedValue((int)DxfCode.Start, "CIRCLE");
Autodesk.AutoCAD.DatabaseServices.DxfCode
с не менее непонятными, взятыми с потолка названиями (что, разумеется, хреново). Можете также создать свое собственное перечисление с необходимыми константами и использовать его (что, сами понимаете, хреново). Добро пожаловать в увлекательный мир программирования! Налево пойдешь — коня потеряешь, и так далее.filterlist[0] = new TypedValue((int)DxfCode.Start, "LINE");
filterlist[0] = new TypedValue((int)DxfCode.Start, "INSERT");
"INSERT"
.filterlist[0] = new TypedValue((int)DxfCode.LayerName, "layer-1");
TypedValue
можно перечислить несколько имен через запятую. В этом случае условия будут объединены операцией «ИЛИ» («OR»).filterlist[0] = new TypedValue((int)DxfCode.Start, "LINE,CIRCLE");
filterlist[0] = new TypedValue((int)DxfCode.LayerName, "layer-1,layer-2");
TypedValue
к массиву условий. В этом случае условия будут объединены операцией «И» («AND»).TypedValue[] filterlist = new TypedValue[2];
filterlist[0] = new TypedValue((int)DxfCode.Start, "CIRCLE");
filterlist[1] = new TypedValue((int)DxfCode.LayerName, "0");
TypedValue[] filterlist = new TypedValue[2];
filterlist[0] = new TypedValue((int)DxfCode.Start, "INSERT");
filterlist[1] = new TypedValue((int)DxfCode.BlockName, "block-1");
TypedValue[] filterlist = new TypedValue[2];
filterlist[0] = new TypedValue((int)DxfCode.Start, "LINE");
filterlist[1] = new TypedValue((int)DxfCode.LayerName, "0,layer-1");
TypedValue
: максимум, чего можно добиться этим способом, — это найти все линии и все круги на обоих слоях сразу.TypedValue
:TypedValue[] filterlist = new TypedValue[10];
filterlist[0] = new TypedValue((int)DxfCode.Operator, "<OR");
filterlist[1] = new TypedValue((int)DxfCode.Operator, "<AND");
filterlist[2] = new TypedValue((int)DxfCode.LayerName, "layer-1");
filterlist[3] = new TypedValue((int)DxfCode.Start, "LINE");
filterlist[4] = new TypedValue((int)DxfCode.Operator, "AND>");
filterlist[5] = new TypedValue((int)DxfCode.Operator, "<AND");
filterlist[6] = new TypedValue((int)DxfCode.LayerName, "layer-2");
filterlist[7] = new TypedValue((int)DxfCode.Start, "CIRCLE");
filterlist[8] = new TypedValue((int)DxfCode.Operator, "AND>");
filterlist[9] = new TypedValue((int)DxfCode.Operator, "OR>");
Layer:layer-2; Type:Autodesk.AutoCAD.DatabaseServices.Circle; Color: 128,255,64
Layer:layer-1; Type:Autodesk.AutoCAD.DatabaseServices.Line; Color: 0,200,255
Layer:layer-1; Type:Autodesk.AutoCAD.DatabaseServices.Line; Color: 255,128,255
Editor.SelectAll()
, есть ряд других способов поиска (точнее, выделения) объектов на чертеже. Вот ссылки: английская документация, русский перевод.Editor.SelectAll()
. Зато мы рассмотрели самый мощный из них.ModelSpace
), а ко всей БД документа целиком. Таким образом, мы увидим не только изображенные на чертеже объекты, но и слои, определения блоков и т.п.// команда для итерации по объектам (подход 3)
// Осторожно! Используется черная магия!
[CommandMethod("Habr_IterateThroughAllObjects_3")]
public void iterateThroughAllObjects_3()
{
Database db = HostApplicationServices.WorkingDatabase;
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
long amount = 0;
Dictionary<string, int> d = new Dictionary<string, int>();
ObjectId id = ObjectId.Null;
for (long i = db.BlockTableId.Handle.Value; i < db.Handseed.Value; i++)
{
Handle h = new Handle(i);
if (db.TryGetObjectId(h, out id) && !id.IsNull && id.IsValid && !id.IsErased)
{
string t = id.ObjectClass.DxfName;
amount++;
if(d.ContainsKey(t))
d[t]++;
else
d.Add(t, 1);
}
}
foreach(KeyValuePair<string,int> kvp in d)
ed.WriteMessage("\n{0}: {1} ", kvp.Key, kvp.Value);
ed.WriteMessage("\nTotal {0} objects in drawing\n", amount);
}
ObjectID
, мы открываем сам объект, приводим его к нужному типу и вносим необходимые изменения в свойства. Ну или удаляем объект с чертежа, используя соответствующий метод.Erase();
[CommandMethod("Habr_EraseCircles_2")]
public void eraseCircles_2()
{
// получаем БД и Editor текущего документа
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
// создаем переменную, в которой будут содержаться данные для фильтра
TypedValue[] filterlist = new TypedValue[1];
// первый аргумент (0) указывает, что мы задаем тип объекта
// второй аргумент ("CIRCLE") - собственно тип
filterlist[0] = new TypedValue(0, "CIRCLE");
// создаем фильтр
SelectionFilter filter = new SelectionFilter(filterlist);
// пытаемся получить ссылки на объекты с учетом фильтра
// ВНИМАНИЕ! Нужно проверить работоспособность метода с замороженными и заблокированными слоями!
PromptSelectionResult selRes = ed.SelectAll(filter);
// если произошла ошибка - сообщаем о ней
if (selRes.Status != PromptStatus.OK)
{
ed.WriteMessage("\nError!\n");
return;
}
// получаем массив ID объектов
ObjectId[] ids = selRes.Value.GetObjectIds();
// начинаем транзакцию
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// "пробегаем" по всем полученным объектам
foreach (ObjectId id in ids)
{
// приводим каждый из них к типу Entity
Entity entity = (Entity)tr.GetObject(id, OpenMode.ForRead);
// открываем приговоренный объект на запись
entity.UpgradeOpen();
// удаляем объект
entity.Erase();
}
tr.Commit();
}
}
UpgradeOpen()
, а сразу открывать объект на запись и удалять:Entity entity = (Entity)tr.GetObject(id, OpenMode.ForWrite);
entity.Erase();
try...catch
с последующим перехватыванием исключений. То есть что-то вроде такого:Entity entity = (Entity)tr.GetObject(id, OpenMode.ForRead);
try
{
entity.UpgradeOpen();
entity.Erase();
}
catch ()
{
ed.WriteMessage("\nSomething went wrong...\n");
}
try...catch
в таком виде — это тот еще быдлокод. Ведь мы же знаем, что в случае заблокированного слоя нас ждет ошибка eOnLockedLayer
, так что можем перехватывать не все ошибки подряд, а только Autodesk.AutoCAD.Runtime.Exception
с соответствующим кодом ошибки (ErrorStatus
) — как-то так:catch (Autodesk.AutoCAD.Runtime.Exception ex)
{
if (ex.ErrorStatus == ErrorStatus.OnLockedLayer)
{
...
}
}
GetObject
, вообще говоря, имеет следующую сигнатуру:GetObject(ObjectId id, OpenMode mode, Boolean openErased, Boolean forceOpenOnLockedLayer)
Entity entity = (Entity)tr.GetObject(id, OpenMode.ForWrite, false, true);
entity.Erase();
try...catch
можно использовать параметр forceOpenOnLockedLayer
. В этом случае мы отказываемся от метода UpgradeOpen()
и сразу открываем объект методом GetObject()
на запись (OpenMode.ForWrite
) с установленным флагом forceOpenOnLockedLayer
.[CommandMethod("Habr_RepaintOrange_2")]
public void repaintOrange_2()
{
// получаем БД и Editor текущего документа
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
// пытаемся получить ссылки на все объекты
// ВНИМАНИЕ! Нужно проверить работоспособность метода с замороженными и заблокированными слоями!
PromptSelectionResult selRes = ed.SelectAll();
// если произошла ошибка - сообщаем о ней
if (selRes.Status != PromptStatus.OK)
{
ed.WriteMessage("\nError!\n");
return;
}
// получаем массив ID объектов
ObjectId[] ids = selRes.Value.GetObjectIds();
// начинаем транзакцию
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// "пробегаем" по всем полученным объектам
foreach (ObjectId id in ids)
{
// приводим каждый из них к типу Entity
Entity entity = (Entity)tr.GetObject(id, OpenMode.ForRead);
// открываем объект на запись
entity.UpgradeOpen();
// изменяем цвет на оранжевый
entity.Color = Autodesk.AutoCAD.Colors.Color.FromRgb(255, 128, 0);
}
tr.Commit();
}
}
Entity
. Но как и в предыдущем случае, вы должны быть на 146% уверены в том, что плагину удастся получить доступ к объекту на запись. Если степень уверенности меньше — используйте флаг forceOpenOnLockedLayer
или try...catch
и перехватывайте возможные исключения.Entity
, мы не сможем это сделать, поскольку у него нет свойства, отвечающего за радиус. В данном случае нужно приводить объект к типу Circle
:[CommandMethod("Habr_ModifyCircles_2")]
public void modifyCircles_2()
{
// получаем БД и Editor текущего документа
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
// создаем переменную, в которой будут содержаться данные для фильтра
TypedValue[] filterlist = new TypedValue[1];
// первый аргумент (0) указывает, что мы задаем тип объекта
// второй аргумент ("CIRCLE") - собственно тип
filterlist[0] = new TypedValue(0, "CIRCLE");
// создаем фильтр
SelectionFilter filter = new SelectionFilter(filterlist);
// пытаемся получить ссылки на объекты с учетом фильтра
// ВНИМАНИЕ! Нужно проверить работоспособность метода с замороженными и заблокированными слоями!
PromptSelectionResult selRes = ed.SelectAll(filter);
// если произошла ошибка - сообщаем о ней
if (selRes.Status != PromptStatus.OK)
{
ed.WriteMessage("\nError!\n");
return;
}
// получаем массив ID объектов
ObjectId[] ids = selRes.Value.GetObjectIds();
// начинаем транзакцию
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// "пробегаем" по всем полученным объектам
foreach (ObjectId id in ids)
{
// приводим каждый из них к типу Circle
Circle cir = (Circle)tr.GetObject(id, OpenMode.ForRead);
// открываем объект на запись
cir.UpgradeOpen();
// увеличиваем радиус
cir.Radius = cir.Radius * 2;
}
tr.Commit();
}
}
Circle
, например, вхождение блока добром не кончится:try...catch
! Или по крайней мере обеспечивайте фильтрацию, как в нашем примере, либо же проверяйте тип непосредственно перед приведением:Entity ent = (Entity)tr.GetObject(id, OpenMode.ForRead);
if (ent.GetType() == typeof(Circle))
{
Circle cir = (Circle)tr.GetObject(id, OpenMode.ForRead);
}
eOnLockedLayer
. Для борьбы с ней используйте либо флаг forceOpenOnLockedLayer
, либо конструкцию try...catch
, либо фильтры / проверки, которые отсекут заблокированные объекты.[CommandMethod("Habr_MoveBlocks_2")]
public void moveBlocks_2()
{
// получаем БД и Editor текущего документа
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
// создаем переменную, в которой будут содержаться данные для фильтра
TypedValue[] filterlist = new TypedValue[1];
// первый аргумент (0) указывает, что мы задаем тип объекта
// второй аргумент ("CIRCLE") - собственно тип
filterlist[0] = new TypedValue(0, "INSERT");
// создаем фильтр
SelectionFilter filter = new SelectionFilter(filterlist);
// пытаемся получить ссылки на объекты с учетом фильтра
// ВНИМАНИЕ! Нужно проверить работоспособность метода с замороженными и заблокированными слоями!
PromptSelectionResult selRes = ed.SelectAll(filter);
// если произошла ошибка - сообщаем о ней
if (selRes.Status != PromptStatus.OK)
{
ed.WriteMessage("\nError!\n");
return;
}
// получаем массив ID объектов
ObjectId[] ids = selRes.Value.GetObjectIds();
// начинаем транзакцию
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// "пробегаем" по всем полученным объектам
foreach (ObjectId id in ids)
{
// приводим каждый из них к типу BlockReference
BlockReference br = (BlockReference)tr.GetObject(id, OpenMode.ForRead);
// открываем объект на запись
br.UpgradeOpen();
// перемещаем вхождение блока
br.Position = Point3d.Origin;
}
tr.Commit();
}
}
Position
для окружности является свойство Center
.using System;
using System.Collections.Generic;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.EditorInput;
using acad = Autodesk.AutoCAD.ApplicationServices.Application;
namespace HabrPlug_SearchAndRescue
{
public class ClassMyAutoCADDLL_SearchAndRescue
{
public class Commands : IExtensionApplication
{
// используемые цвета
Autodesk.AutoCAD.Colors.Color color_Pink = Autodesk.AutoCAD.Colors.Color.FromRgb(255, 128, 255);
Autodesk.AutoCAD.Colors.Color color_Blue = Autodesk.AutoCAD.Colors.Color.FromRgb(0, 200, 255);
Autodesk.AutoCAD.Colors.Color color_LightGreen = Autodesk.AutoCAD.Colors.Color.FromRgb(128, 255, 64);
// ID слоев "layer-1" и "layer-2"
ObjectId layer_1;
ObjectId layer_2;
// создаем слои
public void createLayers()
{
// получаем текущий документ и его БД
Document acDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
Database acCurDb = acDoc.Database;
// блокируем документ
using (DocumentLock docloc = acDoc.LockDocument())
{
// начинаем транзакцию
using (Transaction tr = acCurDb.TransactionManager.StartTransaction())
{
// открываем таблицу слоев документа
LayerTable acLyrTbl = tr.GetObject(acCurDb.LayerTableId, OpenMode.ForWrite) as LayerTable;
// создаем новый слой и задаем ему имя
LayerTableRecord acLyrTblRec_1 = new LayerTableRecord();
acLyrTblRec_1.Name = "layer-1";
// заносим созданный слой в таблицу слоев, сохраняем ID созданной записи слоя
layer_1 = acLyrTbl.Add(acLyrTblRec_1);
// добавляем созданный слой в документ
tr.AddNewlyCreatedDBObject(acLyrTblRec_1, true);
// создаем новый слой и задаем ему имя
LayerTableRecord acLyrTblRec_2 = new LayerTableRecord();
acLyrTblRec_2.Name = "layer-2";
// заносим созданный слой в таблицу слоев, сохраняем ID созданной записи слоя
layer_2 = acLyrTbl.Add(acLyrTblRec_2);
// добавляем созданный слой в документ
tr.AddNewlyCreatedDBObject(acLyrTblRec_2, true);
// фиксируем транзакцию
tr.Commit();
}
}
}
// создаем определение блока "block-1"
public void createBlock_1()
{
// получаем ссылки на документ и его БД
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
// имя создаваемого блока
const string blockName = "block-1";
// начинаем транзакцию
Transaction tr = db.TransactionManager.StartTransaction();
using (tr)
{
// открываем таблицу блоков на запись
BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForWrite);
// проверяем, нет ли в таблице блока с таким именем; если есть - заканчиваем выполнение команды
if (bt.Has(blockName))
{
return;
}
// создаем новое определение блока, задаем ему имя
BlockTableRecord btr = new BlockTableRecord();
btr.Name = blockName;
// добавляем созданное определение блока в таблицу блоков и в транзакцию
bt.Add(btr);
tr.AddNewlyCreatedDBObject(btr, true);
// добавляем к блоку элементы
// создаем окружность
Circle acCircle = new Circle();
// устанавливаем параметры созданного объекта
acCircle.SetDatabaseDefaults();
acCircle.Center = Point3d.Origin;
acCircle.Radius = 25;
// добавляем созданный объект в определение блока и в транзакцию
btr.AppendEntity(acCircle);
tr.AddNewlyCreatedDBObject(acCircle, true);
// создаем линию
Line acLine = new Line(new Point3d(18, 18, 0), new Point3d(35, 35, 0));
// устанавливаем параметры созданного объекта равными параметрам по умолчанию
acLine.SetDatabaseDefaults();
// добавляем созданный объект в определение блока и в транзакцию
btr.AppendEntity(acLine);
tr.AddNewlyCreatedDBObject(acLine, true);
// создаем полилинию
Polyline acPolyline = new Polyline();
// устанавливаем параметры созданного объекта равными параметрам по умолчанию
acPolyline.SetDatabaseDefaults();
// добавляем к полилинии вершины
acPolyline.AddVertexAt(0, new Point2d(20, 35), 0, 0, 0);
acPolyline.AddVertexAt(1, new Point2d(35, 35), 0, 0, 0);
acPolyline.AddVertexAt(2, new Point2d(35, 20), 0, 0, 0);
// добавляем созданный объект в определение блока и в транзакцию
btr.AppendEntity(acPolyline);
tr.AddNewlyCreatedDBObject(acPolyline, true);
// фиксируем транзакцию
tr.Commit();
}
}
// создаем определение блока "block-2"
public void createBlock_2()
{
// получаем ссылки на документ и его БД
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
// имя создаваемого блока
const string blockName = "block-2";
// начинаем транзакцию
Transaction tr = db.TransactionManager.StartTransaction();
using (tr)
{
// открываем таблицу блоков на запись
BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForWrite);
// проверяем, нет ли в таблице блока с таким именем; если есть - заканчиваем выполнение команды
if (bt.Has(blockName))
{
return;
}
// создаем новое определение блока, задаем ему имя
BlockTableRecord btr = new BlockTableRecord();
btr.Name = blockName;
// добавляем созданное определение блока в таблицу блоков и в транзакцию
bt.Add(btr);
tr.AddNewlyCreatedDBObject(btr, true);
// добавляем к блоку элементы
// создаем окружность
Circle acCircle = new Circle();
// устанавливаем параметры созданного объекта
acCircle.SetDatabaseDefaults();
acCircle.Center = Point3d.Origin;
acCircle.Radius = 25;
// добавляем созданный объект определение блока и в транзакцию
btr.AppendEntity(acCircle);
tr.AddNewlyCreatedDBObject(acCircle, true);
// создаем первую линию
Line acLine_1 = new Line(new Point3d(0, -25, 0), new Point3d(0, -50, 0));
// устанавливаем параметры созданного объекта равными параметрам по умолчанию
acLine_1.SetDatabaseDefaults();
// добавляем созданный объект в определение блока и в транзакцию
btr.AppendEntity(acLine_1);
tr.AddNewlyCreatedDBObject(acLine_1, true);
// создаем вторую линию
Line acLine_2 = new Line(new Point3d(-7, -39, 0), new Point3d(7, -39, 0));
// устанавливаем параметры созданного объекта равными параметрам по умолчанию
acLine_2.SetDatabaseDefaults();
// добавляем созданный объект в определение блока и в транзакцию
btr.AppendEntity(acLine_2);
tr.AddNewlyCreatedDBObject(acLine_2, true);
// фиксируем транзакцию
tr.Commit();
}
}
// создаем объекты на нулевом слое
public void layer_0_createObjects()
{
// получаем текущий документ и его БД
Document doc = acad.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
// начинаем транзакцию
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// открываем таблицу блоков документа
BlockTable acBlkTbl;
acBlkTbl = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
// открываем пространство модели (Model Space) - оно является одной из записей в таблице блоков документа
BlockTableRecord ms = tr.GetObject(acBlkTbl[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
// добавляем розовую линию
Line acLine_1 = new Line(new Point3d(225, 225, 0), new Point3d(225, 175, 0));
// устанавливаем параметры созданного объекта равными параметрам по умолчанию
acLine_1.SetDatabaseDefaults();
// устанавливаем для объекта нужный слой и цвет
acLine_1.Layer = "0";
acLine_1.Color = color_Pink;
// добавляем созданный объект в пространство модели и в транзакцию
ms.AppendEntity(acLine_1);
tr.AddNewlyCreatedDBObject(acLine_1, true);
// добавляем голубую линию
Line acLine_2 = new Line(new Point3d(250, 225, 0), new Point3d(250, 175, 0));
// устанавливаем параметры созданного объекта равными параметрам по умолчанию
acLine_2.SetDatabaseDefaults();
// устанавливаем для объекта нужный слой и цвет
acLine_2.Layer = "0";
acLine_2.Color = color_Blue;
// добавляем созданный объект в пространство модели и в транзакцию
ms.AppendEntity(acLine_2);
tr.AddNewlyCreatedDBObject(acLine_2, true);
// добавляем салатовую линию
Line acLine_3 = new Line(new Point3d(275, 225, 0), new Point3d(275, 175, 0));
// устанавливаем параметры созданного объекта равными параметрам по умолчанию
acLine_3.SetDatabaseDefaults();
// устанавливаем для объекта нужный слой и цвет
acLine_3.Layer = "0";
acLine_3.Color = color_LightGreen;
// добавляем созданный объект в пространство модели и в транзакцию
ms.AppendEntity(acLine_3);
tr.AddNewlyCreatedDBObject(acLine_3, true);
// добавляем розовую полилинию
Polyline acPolyline = new Polyline();
// устанавливаем параметры созданного объекта равными параметрам по умолчанию
acPolyline.SetDatabaseDefaults();
// добавляем к полилинии вершины
acPolyline.AddVertexAt(0, new Point2d(300, 225), 0, 0, 0);
acPolyline.AddVertexAt(1, new Point2d(325, 175), 0, 0, 0);
acPolyline.AddVertexAt(2, new Point2d(350, 225), 0, 0, 0);
// устанавливаем для объекта нужный слой и цвет
acPolyline.Layer = "0";
acPolyline.Color = color_Pink;
// добавляем созданный объект в пространство модели и в транзакцию
ms.AppendEntity(acPolyline);
tr.AddNewlyCreatedDBObject(acPolyline, true);
// добавляем голубую окружность
Circle acCircle = new Circle();
// устанавливаем параметры созданного объекта
acCircle.SetDatabaseDefaults();
acCircle.Center = new Point3d(400, 200, 0);
acCircle.Radius = 25;
// устанавливаем для объекта нужный слой и цвет
acCircle.Layer = "0";
acCircle.Color = color_Blue;
// добавляем созданный объект в пространство модели и в транзакцию
ms.AppendEntity(acCircle);
tr.AddNewlyCreatedDBObject(acCircle, true);
// добавляем салатовый текст
DBText text = new DBText();
text.Position = new Point3d(450, 175, 0);
text.Height = 50;
text.TextString = "HABR!";
// устанавливаем для объекта нужный слой и цвет
text.Layer = "0";
text.Color = color_LightGreen;
// добавляем созданный объект в пространство модели и в транзакцию
ms.AppendEntity(text);
tr.AddNewlyCreatedDBObject(text, true);
// фиксируем изменения
tr.Commit();
}
}
// создаем объекты на слое "layer-1"
public void layer_1_createObjects()
{
// получаем текущий документ и его БД
Document doc = acad.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
// начинаем транзакцию
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// запоминаем текущий слой и временно меняем его на нужный нам
// (это позволит не задавать слой отдельно для каждого создаваемого объекта)
ObjectId currentLayer = db.Clayer;
db.Clayer = layer_1;
// открываем таблицу блоков документа
BlockTable acBlkTbl;
acBlkTbl = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
// открываем пространство модели (Model Space) - оно является одной из записей в таблице блоков документа
BlockTableRecord ms = tr.GetObject(acBlkTbl[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
// добавляем розовую линию
Line acLine_1 = new Line(new Point3d(225, 25, 0), new Point3d(225, -25, 0));
// устанавливаем параметры созданного объекта
acLine_1.SetDatabaseDefaults();
acLine_1.Color = color_Pink;
// добавляем созданный объект в пространство модели и в транзакцию
ms.AppendEntity(acLine_1);
tr.AddNewlyCreatedDBObject(acLine_1, true);
// добавляем голубую линию
Line acLine_2 = new Line(new Point3d(250, 25, 0), new Point3d(250, -25, 0));
// устанавливаем параметры созданного объекта
acLine_2.SetDatabaseDefaults();
acLine_2.Color = color_Blue;
// добавляем созданный объект в пространство модели и в транзакцию
ms.AppendEntity(acLine_2);
tr.AddNewlyCreatedDBObject(acLine_2, true);
// добавляем салатовую окружность
Circle acCircle = new Circle();
// устанавливаем параметры созданного объекта
acCircle.SetDatabaseDefaults();
acCircle.Center = new Point3d(300, 0, 0);
acCircle.Radius = 25;
acCircle.Color = color_LightGreen;
// добавляем созданный объект в пространство модели и в транзакцию
ms.AppendEntity(acCircle);
tr.AddNewlyCreatedDBObject(acCircle, true);
// добавляем розовый текст
DBText text = new DBText();
// устанавливаем параметры созданного объекта
text.Position = new Point3d(350, -25, 0);
text.Height = 50;
text.TextString = "HABR!";
text.Color = color_Pink;
// добавляем созданный объект в пространство модели и в транзакцию
ms.AppendEntity(text);
tr.AddNewlyCreatedDBObject(text, true);
// добавляем вхождение блока "block-1"
// открываем таблицу блоков для чтения
BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
// получаем ObjectID блока
ObjectId btrId = bt["block-1"];
// создаем новое вхождение блока, используя полученный ID определения блока
BlockReference br = new BlockReference(new Point3d(600, 0, 0), btrId);
// добавляем вхождение блока на пространство модели и в транзакцию
ms.AppendEntity(br);
tr.AddNewlyCreatedDBObject(br, true);
// возвращаем обратно старый текущий слой
db.Clayer = currentLayer;
// фиксируем изменения
tr.Commit();
}
}
// создаем объекты на слое "layer-2"
public void layer_2_createObjects()
{
// получаем текущий документ и его БД
Document doc = acad.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
// начинаем транзакцию
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// запоминаем текущий слой и временно меняем его на нужный нам
// (это позволит не задавать слой отдельно для каждого создаваемого объекта)
ObjectId currentLayer = db.Clayer;
db.Clayer = layer_2;
// открываем таблицу блоков документа
BlockTable acBlkTbl;
acBlkTbl = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
// открываем пространство модели (Model Space) - оно является одной из записей в таблице блоков документа
BlockTableRecord ms = tr.GetObject(acBlkTbl[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
// добавляем розовую линию
Line acLine_1 = new Line(new Point3d(225, -175, 0), new Point3d(225, -225, 0));
// устанавливаем параметры созданного объекта
acLine_1.SetDatabaseDefaults();
acLine_1.Color = color_Pink;
// добавляем созданный объект в пространство модели и в транзакцию
ms.AppendEntity(acLine_1);
tr.AddNewlyCreatedDBObject(acLine_1, true);
// добавляем голубую дугу
Arc acArc = new Arc(new Point3d(250, -200, 0), 25, -45 / 180.0 * Math.PI, 45 / 180.0 * Math.PI);
// устанавливаем параметры созданного объекта
acArc.SetDatabaseDefaults();
acArc.Color = color_Blue;
// добавляем созданный объект в пространство модели и в транзакцию
ms.AppendEntity(acArc);
tr.AddNewlyCreatedDBObject(acArc, true);
// добавляем салатовую окружность
Circle acCircle = new Circle();
// устанавливаем параметры созданного объекта
acCircle.SetDatabaseDefaults();
acCircle.Center = new Point3d(325, -200, 0);
acCircle.Radius = 25;
acCircle.Color = color_LightGreen;
// добавляем созданный объект в пространство модели и в транзакцию
ms.AppendEntity(acCircle);
tr.AddNewlyCreatedDBObject(acCircle, true);
// добавляем вхождение блока "block-1"
// открываем таблицу блоков для чтения
BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
// получаем ObjectID блока
ObjectId btrId = bt["block-1"];
// создаем новое вхождение блока, используя полученный ID определения блока
BlockReference br = new BlockReference(new Point3d(400, -200, 0), btrId);
// добавляем вхождение блока на пространство модели и в транзакцию
ms.AppendEntity(br);
tr.AddNewlyCreatedDBObject(br, true);
// добавляем вхождение блока "block-2"
// получаем ObjectID блока
btrId = bt["block-2"];
// создаем новое вхождение блока, используя полученный ID определения блока
br = new BlockReference(new Point3d(475, -200, 0), btrId);
// добавляем вхождение блока на пространство модели и в транзакцию
ms.AppendEntity(br);
tr.AddNewlyCreatedDBObject(br, true);
// возвращаем обратно старый текущий слой
db.Clayer = currentLayer;
// фиксируем изменения
tr.Commit();
}
}
// создаем объекты при загрузке плагина
public void Initialize()
{
createLayers();
createBlock_1();
createBlock_2();
layer_0_createObjects();
layer_1_createObjects();
layer_2_createObjects();
}
// функция Terminate() необходима, чтобы реализовать интерфейс IExtensionApplication
public void Terminate()
{
}
//////////////////////////////////////////////////////////////
// ПЕРВЫЙ ВАРИАНТ РЕАЛИЗАЦИИ ПОИСКА (<<MODEL SPACE>>)
//////////////////////////////////////////////////////////////
// команда для итерации по объектам (подход 1)
[CommandMethod("Habr_IterateThroughAllObjects_1")]
public void iterateThroughAllObjects_1()
{
// получаем текущую БД
Database db = HostApplicationServices.WorkingDatabase;
// начинаем транзакцию
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// получаем ссылку на пространство модели (ModelSpace)
BlockTableRecord ms = (BlockTableRecord)tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);
// "пробегаем" по всем объектам в пространстве модели
foreach (ObjectId id in ms)
{
// приводим каждый из них к типу Entity
Entity entity = (Entity)tr.GetObject(id, OpenMode.ForRead);
// выводим в консоль слой (entity.Layer), тип (entity.GetType().ToString()) и цвет (entity.Color) каждого объекта
acad.DocumentManager.MdiActiveDocument.Editor.WriteMessage(string.Format("\nLayer:{0}; Type:{1}; Color: {2},{3},{4}\n",
entity.Layer, entity.GetType().ToString(), entity.Color.Red.ToString(), entity.Color.Green.ToString(), entity.Color.Blue.ToString()));
}
tr.Commit();
}
}
// команда для поиска окружностей (подход 1)
[CommandMethod("Habr_FindCircles_1")]
public void findCircles_1()
{
// получаем текущую БД
Database db = HostApplicationServices.WorkingDatabase;
// начинаем транзакцию
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// получаем ссылку на пространство модели (ModelSpace)
BlockTableRecord ms = (BlockTableRecord)tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);
// "пробегаем" по всем объектам в пространстве модели
foreach (ObjectId id in ms)
{
// приводим каждый из них к типу Entity
Entity entity = (Entity)tr.GetObject(id, OpenMode.ForRead);
// если это окружность - выводим в консоль слой, тип и цвет каждого объекта
if (entity.GetType() == typeof(Circle))
{
acad.DocumentManager.MdiActiveDocument.Editor.WriteMessage(string.Format("\nLayer:{0}; Type:{1}; Color: {2},{3},{4}\n",
entity.Layer, entity.GetType().ToString(), entity.Color.Red.ToString(), entity.Color.Green.ToString(), entity.Color.Blue.ToString()));
}
}
tr.Commit();
}
}
// команда для поиска салатовых объектов (подход 1)
[CommandMethod("Habr_FindLightGreenObjects_1")]
public void findLightGreenObjects_1()
{
// получаем текущую БД
Database db = HostApplicationServices.WorkingDatabase;
// начинаем транзакцию
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// получаем ссылку на пространство модели (ModelSpace)
BlockTableRecord ms = (BlockTableRecord)tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);
// "пробегаем" по всем объектам в пространстве модели
foreach (ObjectId id in ms)
{
// приводим каждый из них к типу Entity
Entity entity = (Entity)tr.GetObject(id, OpenMode.ForRead);
// если цвет объекта - салатовый, то выводим в консоль слой, тип и цвет каждого объекта
if (entity.Color == Autodesk.AutoCAD.Colors.Color.FromRgb(128, 255, 64))
{
acad.DocumentManager.MdiActiveDocument.Editor.WriteMessage(string.Format("\nLayer:{0}; Type:{1}; Color: {2},{3},{4}\n",
entity.Layer, entity.GetType().ToString(), entity.Color.Red.ToString(), entity.Color.Green.ToString(), entity.Color.Blue.ToString()));
}
}
tr.Commit();
}
}
// команда для поиска всех вхождений блока "block-1" (подход 1)
[CommandMethod("Habr_FindBlocks_1")]
public void findBlocks_1()
{
// получаем текущую БД
Database db = HostApplicationServices.WorkingDatabase;
// начинаем транзакцию
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// получаем ссылку на пространство модели (ModelSpace)
BlockTableRecord ms = (BlockTableRecord)tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);
// "пробегаем" по всем объектам в пространстве модели
foreach (ObjectId id in ms)
{
// приводим каждый из них к типу Entity
Entity entity = (Entity)tr.GetObject(id, OpenMode.ForRead);
// проверяем, является ли объект вхождением блока
if (entity.GetType() == typeof(BlockReference))
{
// если является - приводим его к типу BlockReference
BlockReference br = (BlockReference)entity;
// если имя соответствующего определения блока - "block-1", то выводим в консоль слой, тип и цвет каждого объекта
if (br.Name == "block-1")
{
acad.DocumentManager.MdiActiveDocument.Editor.WriteMessage(string.Format("\nLayer:{0}; Type:{1}; Color: {2},{3},{4}\n",
entity.Layer, entity.GetType().ToString(), entity.Color.Red.ToString(), entity.Color.Green.ToString(), entity.Color.Blue.ToString()));
}
}
}
tr.Commit();
}
}
//////////////////////////////////////////////////////////////
// ВТОРОЙ ВАРИАНТ РЕАЛИЗАЦИИ ПОИСКА (<<EDITOR.SELECTALL>>)
//////////////////////////////////////////////////////////////
// команда для итерации по объектам (подход 2)
[CommandMethod("Habr_IterateThroughAllObjects_2")]
public void iterateThroughAllObjects_2()
{
// получаем БД и Editor текущего документа
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
// пытаемся получить ссылки на все объекты
// ВНИМАНИЕ! Нужно проверить работоспособность метода с замороженными и заблокированными слоями!
PromptSelectionResult selRes = ed.SelectAll();
// если произошла ошибка - сообщаем о ней
if (selRes.Status != PromptStatus.OK)
{
ed.WriteMessage("\nError!\n");
return;
}
// получаем массив ID объектов
ObjectId[] ids = selRes.Value.GetObjectIds();
// начинаем транзакцию
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// "пробегаем" по всем полученным объектам
foreach (ObjectId id in ids)
{
// приводим каждый из них к типу Entity
Entity entity = (Entity)tr.GetObject(id, OpenMode.ForRead);
// выводим в консоль слой (entity.Layer), тип (entity.GetType().ToString()) и цвет (entity.Color) каждого объекта
acad.DocumentManager.MdiActiveDocument.Editor.WriteMessage(string.Format("\nLayer:{0}; Type:{1}; Color: {2},{3},{4}\n",
entity.Layer, entity.GetType().ToString(), entity.Color.Red.ToString(), entity.Color.Green.ToString(), entity.Color.Blue.ToString()));
}
tr.Commit();
}
}
// команда для поиска окружностей (подход 2)
[CommandMethod("Habr_FindCircles_2")]
public void findCircles_2()
{
// получаем БД и Editor текущего документа
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
// создаем переменную, в которой будут содержаться данные для фильтра
TypedValue[] filterlist = new TypedValue[1];
// первый аргумент (0) указывает, что мы задаем тип объекта
// второй аргумент ("CIRCLE") - собственно тип
filterlist[0] = new TypedValue(0, "CIRCLE");
// создаем фильтр
SelectionFilter filter = new SelectionFilter(filterlist);
// пытаемся получить ссылки на объекты с учетом фильтра
// ВНИМАНИЕ! Нужно проверить работоспособность метода с замороженными и заблокированными слоями!
PromptSelectionResult selRes = ed.SelectAll(filter);
// если произошла ошибка - сообщаем о ней
if (selRes.Status != PromptStatus.OK)
{
ed.WriteMessage("\nError!\n");
return;
}
// получаем массив ID объектов
ObjectId[] ids = selRes.Value.GetObjectIds();
// начинаем транзакцию
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// "пробегаем" по всем полученным объектам
foreach (ObjectId id in ids)
{
// приводим каждый из них к типу Entity
Entity entity = (Entity)tr.GetObject(id, OpenMode.ForRead);
// выводим в консоль слой, тип и цвет каждого объекта
acad.DocumentManager.MdiActiveDocument.Editor.WriteMessage(string.Format("\nLayer:{0}; Type:{1}; Color: {2},{3},{4}\n",
entity.Layer, entity.GetType().ToString(), entity.Color.Red.ToString(), entity.Color.Green.ToString(), entity.Color.Blue.ToString()));
}
tr.Commit();
}
}
//////////////////////////////////////////////////////////////
// РЕДАКТИРОВАНИЕ ОБЪЕКТОВ
//////////////////////////////////////////////////////////////
// команда для удаления окружностей
[CommandMethod("Habr_EraseCircles_2")]
public void eraseCircles_2()
{
// получаем БД и Editor текущего документа
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
// создаем переменную, в которой будут содержаться данные для фильтра
TypedValue[] filterlist = new TypedValue[1];
// первый аргумент (0) указывает, что мы задаем тип объекта
// второй аргумент ("CIRCLE") - собственно тип
filterlist[0] = new TypedValue(0, "CIRCLE");
// создаем фильтр
SelectionFilter filter = new SelectionFilter(filterlist);
// пытаемся получить ссылки на объекты с учетом фильтра
// ВНИМАНИЕ! Нужно проверить работоспособность метода с замороженными и заблокированными слоями!
PromptSelectionResult selRes = ed.SelectAll(filter);
// если произошла ошибка - сообщаем о ней
if (selRes.Status != PromptStatus.OK)
{
ed.WriteMessage("\nError!\n");
return;
}
// получаем массив ID объектов
ObjectId[] ids = selRes.Value.GetObjectIds();
// начинаем транзакцию
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// "пробегаем" по всем полученным объектам
foreach (ObjectId id in ids)
{
// приводим каждый из них к типу Entity
Entity entity = (Entity)tr.GetObject(id, OpenMode.ForRead);
// открываем приговоренный объект на запись
entity.UpgradeOpen();
// удаляем объект
entity.Erase();
}
tr.Commit();
}
}
// команда для перекраски всех объектов в оранжевый цвет
[CommandMethod("Habr_RepaintOrange_2")]
public void repaintOrange_2()
{
// получаем БД и Editor текущего документа
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
// пытаемся получить ссылки на все объекты
// ВНИМАНИЕ! Нужно проверить работоспособность метода с замороженными и заблокированными слоями!
PromptSelectionResult selRes = ed.SelectAll();
// если произошла ошибка - сообщаем о ней
if (selRes.Status != PromptStatus.OK)
{
ed.WriteMessage("\nError!\n");
return;
}
// получаем массив ID объектов
ObjectId[] ids = selRes.Value.GetObjectIds();
// начинаем транзакцию
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// "пробегаем" по всем полученным объектам
foreach (ObjectId id in ids)
{
// приводим каждый из них к типу Entity
Entity entity = (Entity)tr.GetObject(id, OpenMode.ForRead);
// открываем объект на запись
entity.UpgradeOpen();
// изменяем цвет на оранжевый
entity.Color = Autodesk.AutoCAD.Colors.Color.FromRgb(255, 128, 0);
}
tr.Commit();
}
}
// команда для изменения радиуса окружностей
[CommandMethod("Habr_ModifyCircles_2")]
public void modifyCircles_2()
{
// получаем БД и Editor текущего документа
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
// создаем переменную, в которой будут содержаться данные для фильтра
TypedValue[] filterlist = new TypedValue[1];
// первый аргумент (0) указывает, что мы задаем тип объекта
// второй аргумент ("CIRCLE") - собственно тип
filterlist[0] = new TypedValue(0, "CIRCLE");
// создаем фильтр
SelectionFilter filter = new SelectionFilter(filterlist);
// пытаемся получить ссылки на объекты с учетом фильтра
// ВНИМАНИЕ! Нужно проверить работоспособность метода с замороженными и заблокированными слоями!
PromptSelectionResult selRes = ed.SelectAll(filter);
// если произошла ошибка - сообщаем о ней
if (selRes.Status != PromptStatus.OK)
{
ed.WriteMessage("\nError!\n");
return;
}
// получаем массив ID объектов
ObjectId[] ids = selRes.Value.GetObjectIds();
// начинаем транзакцию
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// "пробегаем" по всем полученным объектам
foreach (ObjectId id in ids)
{
// приводим каждый из них к типу Circle
Circle cir = (Circle)tr.GetObject(id, OpenMode.ForRead);
// открываем объект на запись
cir.UpgradeOpen();
// увеличиваем радиус
cir.Radius = cir.Radius * 2;
}
tr.Commit();
}
}
// команда для перемещения блоков
[CommandMethod("Habr_MoveBlocks_2")]
public void moveBlocks_2()
{
// получаем БД и Editor текущего документа
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
// создаем переменную, в которой будут содержаться данные для фильтра
TypedValue[] filterlist = new TypedValue[1];
// первый аргумент (0) указывает, что мы задаем тип объекта
// второй аргумент ("INSERT") - собственно тип
filterlist[0] = new TypedValue(0, "INSERT");
// создаем фильтр
SelectionFilter filter = new SelectionFilter(filterlist);
// пытаемся получить ссылки на объекты с учетом фильтра
// ВНИМАНИЕ! Нужно проверить работоспособность метода с замороженными и заблокированными слоями!
PromptSelectionResult selRes = ed.SelectAll(filter);
// если произошла ошибка - сообщаем о ней
if (selRes.Status != PromptStatus.OK)
{
ed.WriteMessage("\nError!\n");
return;
}
// получаем массив ID объектов
ObjectId[] ids = selRes.Value.GetObjectIds();
// начинаем транзакцию
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// "пробегаем" по всем полученным объектам
foreach (ObjectId id in ids)
{
// приводим каждый из них к типу BlockReference
BlockReference br = (BlockReference)tr.GetObject(id, OpenMode.ForRead);
// открываем объект на запись
br.UpgradeOpen();
// перемещаем вхождение блока
br.Position = Point3d.Origin;
}
tr.Commit();
}
}
//////////////////////////////////////////////////////////////
// БОНУСНЫЙ ВАРИАНТ РЕАЛИЗАЦИИ ПОИСКА (<<ЧЕРНАЯ МАГИЯ>>)
//////////////////////////////////////////////////////////////
// команда для итерации по объектам (подход 3)
// Осторожно! Используется черная магия!
[CommandMethod("Habr_IterateThroughAllObjects_3")]
public void iterateThroughAllObjects_3()
{
Database db = HostApplicationServices.WorkingDatabase;
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
long amount = 0;
Dictionary<string, int> d = new Dictionary<string, int>();
ObjectId id = ObjectId.Null;
for (long i = db.BlockTableId.Handle.Value; i < db.Handseed.Value; i++)
{
Handle h = new Handle(i);
if (db.TryGetObjectId(h, out id) && !id.IsNull && id.IsValid && !id.IsErased)
{
string t = id.ObjectClass.DxfName;
amount++;
if (d.ContainsKey(t))
d[t]++;
else
d.Add(t, 1);
}
}
foreach (KeyValuePair<string, int> kvp in d)
ed.WriteMessage("\n{0}: {1} ", kvp.Key, kvp.Value);
ed.WriteMessage("\nTotal {0} objects in drawing\n", amount);
}
}
}
}
К сожалению, не доступен сервер mySQL