Рисуем снежинку по кривой Коха в Autocad .NET API C#
Сегодня напишем простенький плагин для Autocad, который при вводе команды Snowflake будет автоматически рисовать снежинку из полилиний.
Конечно же, подразумевается, что вы умеете работать с Visual Studio и знакомы с программой Autocad.
При создании я использовал версию Autocad 2017 и Visual Studio 2017. Для успешной работы необходимо добавить в среду разработки ссылки на такие библиотеки как AcCoreMgd, AcDbMgd, AcMgd. О том, как добавить и где скачать эти библиотеки можно узнать в сети Интернет.
Итак, для построения снежинки будем использовать кривую Коха (можете о ней почитать в интернете). Сама снежинка будет иметь бесконечный периметр, но все же ограничена конечной областью плоскости. Для ее создания используем равносторонний треугольник, разделив каждую из его сторон на три части и по каждой из трех центральных третей построим по равностороннему треугольнику меньших размеров. Таким образом, повторяя это построение бесконечное множество раз, получим фрактальный объект, называемый кривой Коха.
Рабочий код:
using Autodesk.AutoCAD.Runtime; using AcadApp = Autodesk.AutoCAD.ApplicationServices.Core.Application; using AcadTransMgr = Autodesk.AutoCAD.DatabaseServices.TransactionManager; using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.Geometry; using Autodesk.AutoCAD.EditorInput; namespace KochSnowflake { public class Class1 { const int color1 = 3; const int color2 = 5; [CommandMethod("Snowflake")] public void Snowflake() { Document doc = AcadApp.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor editor = doc.Editor; AcadTransMgr transMgr = db.TransactionManager; Point2d point1 = new Point2d(2000, 2000); Point2d point2 = new Point2d(5000, 2000); Point2d point3 = new Point2d(3500, 4000); using (Transaction baseTransaction = transMgr.StartTransaction()) { BlockTable BlockTable; BlockTable = baseTransaction.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable; BlockTableRecord blockTableRecord; blockTableRecord = baseTransaction.GetObject(BlockTable[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord; DrawLine(baseTransaction, blockTableRecord, point1, point2, 3); DrawLine(baseTransaction, blockTableRecord, point2, point3, 3); DrawLine(baseTransaction, blockTableRecord, point3, point1, 3); Fractal(baseTransaction, blockTableRecord, point1, point2, point3, 5); Fractal(baseTransaction, blockTableRecord, point2, point3, point1, 5); Fractal(baseTransaction, blockTableRecord, point3, point1, point2, 5); // Находим синии полилинии TypedValue[] filterlist = new TypedValue[2] { new TypedValue((int)DxfCode.Start, "LWPOLYLINE"), new TypedValue((int)DxfCode.Color, 5) }; SelectionFilter filter = new SelectionFilter(filterlist); PromptSelectionResult selResult = editor.SelectAll(filter); if (selResult.Status != PromptStatus.OK) { return; } ObjectId[] objectIds = selResult.Value.GetObjectIds(); foreach (var ObjectId in objectIds) { Polyline polyline = ObjectId.GetObject(OpenMode.ForRead) as Polyline; // Удаляем полилинии polyline.Erase(); } baseTransaction.Commit(); } } private void DrawLine(Transaction transaction, BlockTableRecord blockTableRecord, Point2d point1, Point2d point2, int color) { using (Polyline triangle = new Polyline()) { triangle.AddVertexAt(0, point1, 0, 0, 0); triangle.AddVertexAt(1, point2, 0, 0, 0); triangle.ColorIndex = color; blockTableRecord.AppendEntity(triangle); transaction.AddNewlyCreatedDBObject(triangle, true); } } private int Fractal(Transaction transaction, BlockTableRecord blockTableRecord, Point2d point1, Point2d point2, Point2d point3, int countIteration = 0) { if (countIteration > 0) { // Средняя треть отрезка Point2d point4 = new Point2d((point2.X + 2 * point1.X) / 3, (point2.Y + 2 * point1.Y) / 3); Point2d point5 = new Point2d((2 * point2.X + point1.X) / 3, (point1.Y + 2 * point2.Y) / 3); // Координаты вершины угла Point2d ps = new Point2d((point2.X + point1.X) / 2, (point2.Y + point1.Y) / 2); Point2d pn = new Point2d((4 * ps.X - point3.X) / 3, (4 * ps.Y - point3.Y) / 3); // Рисуем треугольники DrawLine(transaction, blockTableRecord, point4, pn, color1); DrawLine(transaction, blockTableRecord, point5, pn, color1); DrawLine(transaction, blockTableRecord, point4, point5, color2); // Рекурсивный вызов необходимое кол-во раз Fractal(transaction, blockTableRecord, point4, pn, point5, countIteration - 1); Fractal(transaction, blockTableRecord, pn, point5, point4, countIteration - 1); Fractal(transaction, blockTableRecord, point1, point4, new Point2d((2 * point1.X + point3.X) / 3, (2 * point1.Y + point3.Y) / 3), countIteration - 1); Fractal(transaction, blockTableRecord, point5, point2, new Point2d((2 * point2.X + point3.X) / 3, (2 * point2.Y + point3.Y) / 3), countIteration - 1); } return countIteration; } } }
Я не являюсь автором данного кода. Посмотреть его оригинальную реализацию можно здесь. Хотя, немного я его изменил и адаптировал под нужды плагина для Autocad.
Далее, необходимо скомпилировать библиотеку в DLL и загрузить ее в autocad с помощью команды NETLOAD. Сам же плагин вызывается с помощью команды SNOWFLAKE.
Отмечу, используемый мой код далеко не идеален, всего лишь демонстрирует быстрое построение определенного объекта с помощью средств autocad.
Спасибо за внимание.