Is it possible to programmatically create a spatial filter like XCLIP command in .Net? Unfortunately the AcDbIndexFilterManager::addFilter method is not exposed, but we can P/Invoke it. The following C# sample illustrates how to do that. Note that some version specific decorated names are used (see EntryPoint parameter), which can cause this code not to work on other versions.
// required ObjectARX methods, called with P/Invoke // this is valid for R19 release (AutoCAD 2013) [DllImport("acdb19.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "?addFilter@AcDbIndexFilterManager@@YA?AW4ErrorStatus@Acad@@PAVAcDbBlockReference@@PAVAcDbFilter@@@Z")] private static extern int addFilter32(IntPtr pBlkRef, IntPtr pFilter); [DllImport("acdb19.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "?addFilter@AcDbIndexFilterManager@@YA?AW4ErrorStatus@Acad@@PEAVAcDbBlockReference@@PEAVAcDbFilter@@@Z")] private static extern int addFilter64(IntPtr pBlkRef, IntPtr pFilter); /// /// Check if the OS is 32 or 64 bit /// static public bool is64bits { get { return (Application.GetSystemVariable ("PLATFORM").ToString().IndexOf("64") > 0); } } //Create a spatial filter on the selected block reference //create rectangular cliping area by providing the 2 corners [CommandMethod("NetClip")] public void NetClip() { // required variables Document doc = Application.DocumentManager. MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; // select a block reference PromptEntityOptions peo = new PromptEntityOptions( "nSelect a block reference: "); peo.SetRejectMessage("nMust be a block reference..."); peo.AddAllowedClass(typeof(BlockReference), true); PromptEntityResult per = ed.GetEntity(peo); if (per.Status != PromptStatus.OK) return; PromptPointOptions ppo = new PromptPointOptions( "nSelect rect clip 1st corner: "); PromptPointResult ppr1 = ed.GetPoint(ppo); if (ppr1.Status != PromptStatus.OK) return; PromptCornerOptions pco = new PromptCornerOptions( "nSelect rect clip 2nd corner: ", ppr1.Value); pco.UseDashedLine = true; PromptPointResult ppr2 = ed.GetCorner(pco); if (ppr2.Status != PromptStatus.OK) retur
n; using (Transaction trans = db.TransactionManager .StartTransaction()) { BlockReference bref = trans.GetObject(per.ObjectId, OpenMode.ForWrite) as BlockReference; //Define clip rectangle Point3d pt3d1 = ppr1.Value.TransformBy( bref.BlockTransform.Inverse()); Point3d pt3d2 = ppr2.Value.TransformBy( bref.BlockTransform.Inverse()); Point2dCollection boundary = GetClipRectangle(pt3d1, pt3d2); double elevation = 0.0; SpatialFilter filter = new SpatialFilter(); filter.Definition = new SpatialFilterDefinition(boundary, bref.Normal, elevation, 1000, -1000, true); //P/Invoke AcDbIndexFilterManager::addFilter int es; if (is64bits) es = addFilter64(bref.UnmanagedObject, filter.UnmanagedObject); else es = addFilter32(bref.UnmanagedObject, filter.UnmanagedObject); if (es == 0) { ed.WriteMessage( "nSpatial filter
added successfully..."); DrawClipBoundary(boundary, bref, bref.Normal, elevation); } else { ed.WriteMessage( "nSpatial filter failed:(...Error code:" + es.ToString()); }; // need to explicitely close the filter filter.Close(); trans.Commit(); } } // the clip rectangle needs to be provided // with (lower-left, upper-right) so we may // need to re-arrange depending on how the // user selected corners Point2dCollection GetClipRectangle( Point3d p1, Point3d p2) { Point2dCollection clipRect = new Point2dCollection(); double minX = p1.X; double minY = p1.Y; double maxX = p2.X; double maxY = p2.Y; if (minX > p2.X) { minX = p2.X; maxX = p1.X; } if (minY > p2.Y) { minY = p2.Y; maxY = p1.Y; } clipRect.Add(new Point2d(minX, minY)); clipRect.Add(new Point2d(maxX, maxY)); return clipRect; } //Just an optional method in order to visualize the clip area void DrawClipBoundary( Point2dCollection boundary, BlockReference bref, Vector3d Normal, double elevation) { Database db = HostApplicationServices. WorkingDatabase; using (Transaction trans = db.TransactionManager.StartTransaction()) { BlockTable bT = trans.GetObject( db.BlockTableId, OpenMode.ForRead) as BlockTable; BlockTableRecord bTR = trans.GetObject( bT[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord; Polyline pline = new Polyline(); pline.Closed = true; pline.Thickness = 0.0; pline.SetPropertiesFrom(bref); pline.Normal = Normal; pline.Elevation = elevation; pline.ColorIndex = 1; pline.AddVertexAt(0, new Point2d( boundary[0].X, boundary[0].Y), 0, 0, 0); pline.AddVertexAt(1, new Point2d( boundary[0].X, boundary[1].Y), 0, 0, 0); pline.AddVertexAt(2, new Point2d( boundary[1].X, boundary[1].Y), 0, 0, 0); pline.AddVertexAt(3, new Point2d( boundary[1].X, boundary[0].Y), 0, 0, 0); pline.TransformBy(bref.BlockTransform); bTR.AppendEntity(pline); trans.AddNewlyCreatedDBObject(pline, true); trans.Commit(); } }

Leave a Reply to Augusto GoncalvesCancel reply