28/06/2016
Выполнение подрезки блока или внешней ссылки при помощи .NET
Вопрос: Как средствами AutoCAD .NET API можно выполнить подрезку блока или внешней ссылки (по аналогии с командой _XCLIP)
Ответ: Для этой цели используется пространственный фильтр (SpatialFilter). Следующий код показывает как выполнить подрезку блока/внешней ссылки при помощи произвольного замкнутого многоугольника:
Код - C#: [Выделить]
- using Autodesk.AutoCAD.DatabaseServices;
- using Autodesk.AutoCAD.EditorInput;
- using Autodesk.AutoCAD.Geometry;
- using Autodesk.AutoCAD.ApplicationServices;
- using Autodesk.AutoCAD.DatabaseServices.Filters;
- using Autodesk.AutoCAD.Runtime;
- using System;
- namespace SpatialFiltering
- {
- public class ClipBlock
- {
- const string filterDictName = "ACAD_FILTER";
- const string spatialName = "SPATIAL";
- [CommandMethod("XCLIPBREF")]
- public static void clipBlockTest()
- {
- Document doc = Application.DocumentManager.MdiActiveDocument;
- Database db = doc.Database;
- Editor ed = doc.Editor;
- // Выбираем блок для подрезки
- PromptEntityOptions peo =
- new PromptEntityOptions("\nВыберите вставку блока или внешнюю ссылку:");
- peo.AllowNone = false;
- peo.SetRejectMessage("\nЭто не вставка блока и не внешняя ссылка.");
- peo.AddAllowedClass(typeof(BlockReference), false);
- PromptEntityResult per = ed.GetEntity(peo);
- if (per.Status != PromptStatus.OK)
- return;
- Point3dCollection pts3d = new Point3dCollection();
- // Выбираем точки для подрезки
- while (true)
- {
- PromptPointOptions ppo;
- if (pts3d.Count < 3) {
- ppo = new PromptPointOptions("\nУкажите " + (pts3d.Count + 1).ToString() + "-ую точку контура");
- ppo.AllowNone = false;
- } else {
- ppo = new PromptPointOptions("\nУкажите " + (pts3d.Count + 1).ToString() + "-ую точку контура (ENTER - завершение)");
- ppo.AllowNone = true;
- }
- if (pts3d.Count > 0)
- {
- ppo.BasePoint = pts3d[pts3d.Count-1];
- ppo.UseBasePoint = true;
- }
- PromptPointResult ppr = ed.GetPoint(ppo);
- if (ppr.Status != PromptStatus.OK)
- break;
- if (pts3d.Count > 0)
- ed.DrawVector(pts3d[pts3d.Count - 1], ppr.Value, 1, true);
- pts3d.Add(ppr.Value);
- }
- Transaction tr = db.TransactionManager.StartTransaction();
- using (tr)
- {
- // Преобразуем точки в систему координат блока!!!
- BlockReference br = (BlockReference)tr.GetObject(per.ObjectId, OpenMode.ForRead);
- Point2dCollection pts = new Point2dCollection(pts3d.Count);
- Matrix3d mat = br.BlockTransform.Inverse();
- foreach (Point3d p in pts3d)
- {
- Point3d pBlk = p.TransformBy(mat);
- pts.Add(new Point2d(pBlk.X, pBlk.Y));
- }
- // Создаем фильтр
- SpatialFilterDefinition sfd =
- new SpatialFilterDefinition(
- pts, Vector3d.ZAxis, 0.0, 0.0, 0.0, true
- );
- SpatialFilter sf = new SpatialFilter();
- sf.Definition = sfd;
- // Создаем ExtDict если его еще не было
- if (br.ExtensionDictionary == ObjectId.Null)
- {
- br.UpgradeOpen();
- br.CreateExtensionDictionary();
- br.DowngradeOpen();
- }
- // Добавляем фильтр
- DBDictionary xDict = (DBDictionary)tr.GetObject(br.ExtensionDictionary, OpenMode.ForWrite);
- if (xDict.Contains(filterDictName))
- {
- DBDictionary fDict =
- (DBDictionary)tr.GetObject(
- xDict.GetAt(filterDictName), OpenMode.ForWrite
- );
- if (fDict.Contains(spatialName))
- fDict.Remove(spatialName);
- fDict.SetAt(spatialName, sf);
- }
- else
- {
- DBDictionary fDict = new DBDictionary();
- xDict.SetAt(filterDictName, fDict);
- tr.AddNewlyCreatedDBObject(fDict, true);
- fDict.SetAt(spatialName, sf);
- }
- tr.AddNewlyCreatedDBObject(sf, true);
- tr.Commit();
- }
- ed.Regen();
- }
- }
- }
Видео:
Автор: Александр Ривилис
Отредактировано 28.06.2016 в 17:06:47
Обсуждение: http://adn-cis.org/forum/index.php?topic=7181
Опубликовано 28.06.2016Отредактировано 28.06.2016 в 17:06:47