using System;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.DatabaseServices.Filters;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.EditorInput;
using AcRx = Autodesk.AutoCAD.Runtime;
using AcAp = Autodesk.AutoCAD.ApplicationServices;
using AcDb = Autodesk.AutoCAD.DatabaseServices;
using AcGe = Autodesk.AutoCAD.Geometry;
using AcEd = Autodesk.AutoCAD.EditorInput;
[assembly: CommandClass(typeof(Utils.ClipBoundary))]
namespace Utils
{
public class ClipBoundary
{
[CommandMethod("GetXclipBoundary", CommandFlags.Modal)]
public void GetXclipBoundary()
{
AcAp.Document doc = AcAp.Application.DocumentManager.MdiActiveDocument;
AcDb.Database db = doc.Database;
AcEd.Editor ed = doc.Editor;
AcEd.PromptEntityOptions opt =
new AcEd.PromptEntityOptions("\nВыберите блок или внешнюю ссылку с подрезкой: ");
opt.SetRejectMessage("\nЭто не блок и не внешняя ссылка!");
opt.AddAllowedClass(typeof(AcDb.BlockReference),false);
AcEd.PromptEntityResult res = ed.GetEntity(opt);
if (res.Status != AcEd.PromptStatus.OK) return;
using (AcDb.BlockReference bref =
res.ObjectId.Open(AcDb.OpenMode.ForRead) as AcDb.BlockReference) {
AcDb.ObjectId idExt = bref.ExtensionDictionary;
if (idExt.IsNull) {
ed.WriteMessage("\nНет подрезки!");
return;
}
using (AcDb.DBDictionary extDict =
idExt.Open(AcDb.OpenMode.ForRead) as AcDb.DBDictionary) {
if (!extDict.Contains("ACAD_FILTER")) {
ed.WriteMessage("\nНет подрезки!");
return;
}
using (AcDb.DBDictionary dict =
extDict.GetAt("ACAD_FILTER").Open(AcDb.OpenMode.ForRead) as AcDb.DBDictionary) {
if (!dict.Contains("SPATIAL")) {
ed.WriteMessage("\nНет подрезки!");
return;
}
using (AcDb.Filters.SpatialFilter filter =
dict.GetAt("SPATIAL").Open(AcDb.OpenMode.ForRead) as AcDb.Filters.SpatialFilter) {
//////////////////////////////////////////////////////////////////////////
// Получение итоговой матрицы преобразования
//////////////////////////////////////////////////////////////////////////
AcGe.Matrix3d xformInBoundary = filter.ClipSpaceToWorldCoordinateSystemTransform;
AcGe.Matrix3d xformRefOrig = filter.OriginalInverseBlockTransform;
AcGe.Matrix3d refMatrix = bref.BlockTransform;
refMatrix = refMatrix.PostMultiplyBy(xformRefOrig);
AcGe.Matrix3d finalMatrix = refMatrix.PostMultiplyBy(xformInBoundary);
//////////////////////////////////////////////////////////////////////////
AcDb.Filters.SpatialFilterDefinition def = filter.Definition;
AcGe.Point2dCollection pts = def.GetPoints();
if (pts.Count == 2) {
// Если граница - прямоугольник
AcGe.Point2d p1 = new AcGe.Point2d(pts[1].X, pts[0].Y);
AcGe.Point2d p3 = new AcGe.Point2d(pts[0].X, pts[1].Y);
pts.Insert(1, p1); pts.Add(p3);
}
AcGe.Point3dCollection pts3d = new AcGe.Point3dCollection();
for (int i = 0; i < pts.Count; i++) {
AcGe.Point3d p = new AcGe.Point3d(pts[i].X, pts[i].Y, 0);
p = p.TransformBy(finalMatrix);
pts3d.Add(p);
pts[i] = new AcGe.Point2d(pts3d[i].X, pts3d[i].Y);
}
AcGe.Vector3d norm = def.Normal.TransformBy(finalMatrix);
AcGe.Matrix3d plineECS = new AcGe.Matrix3d();
using (AcDb.Polyline poly = new AcDb.Polyline()) {
poly.Normal = norm; plineECS = poly.Ecs;
}
AcGe.Matrix3d plineECSInv = plineECS.Inverse();
AcGe.Point3d ptEcs = pts3d[0];
ptEcs.TransformBy(plineECSInv);
double elev = ptEcs.Z;
using (AcDb.Polyline poly = new AcDb.Polyline(pts.Count)) {
AcDb.ObjectId ownId = bref.OwnerId;
poly.SetPropertiesFrom(bref);
poly.Normal = norm;
for (int i = 0; i < pts.Count; i++) {
poly.AddVertexAt(i, pts[i], 0, 0, 0);
}
poly.Elevation = elev;
poly.ColorIndex = 1; // Установим красный цвет для границы
poly.Closed = true;
using (AcDb.BlockTableRecord btr =
ownId.Open(AcDb.OpenMode.ForWrite) as AcDb.BlockTableRecord) {
btr.AppendEntity(poly);
}
}
}
}
}
}
}
}
}