is there any method without looking throgh all the blockrenferences?
Solved! Go to Solution.
Solved by Hallex. Go to Solution.
Try this code
<CommandMethod("CSW")> _ Public Sub TestSelectWindow() Dim doc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument Dim db As Database = doc.Database Dim ed As Editor = doc.Editor '' dummy object types for test: Dim objects() As String = New String() {"INSERT", "LINE", "LWPOLYLINE", "CIRCLE"} '' dummy layers for test: Dim layers() As String = New String() {"DIM", "DWGRU", "ANNO-TLB", "Defpoints"} Dim layerfilt As String = String.Join(",", layers) Dim objfilt As String = String.Join(",", objects) '' Create a TypedValue array to define the filter by object types (dxf code 0) and layers (dxf code 8) Dim tvs() As TypedValue = New TypedValue() {New TypedValue(0, objfilt), New TypedValue(8, layerfilt)} '' Assign the filter criteria to a SelectionFilter object Dim filter As SelectionFilter = New SelectionFilter(tvs) Dim ppo As PromptPointOptions = New PromptPointOptions(vbLf & "Specify lower legt corner of window: ") Dim pres As PromptPointResult = ed.GetPoint(ppo) If pres.Status <> PromptStatus.OK Then Return Dim p1 As Point3d = pres.Value Dim pco As PromptCornerOptions = New PromptCornerOptions(vbLf & "Opposite corner point: ", p1) pres = ed.GetCorner(pco) If pres.Status <> PromptStatus.OK Then Return Dim p2 As Point3d = pres.Value '' Request for objects to be selected in the drawing area Dim res As PromptSelectionResult res = ed.SelectCrossingWindow(p1, p2, filter) '' If the prompt status is OK, objects were selected 'If res.Status = PromptStatus.OK Then Dim sset As SelectionSet = res.Value If sset.Count > 0 Then Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog("Number of objects selected: " & sset.Count.ToString) Else Return End If Using tr As Transaction = db.TransactionManager.StartTransaction() Try For Each sobj As SelectedObject In sset Dim ent As Entity = DirectCast(tr.GetObject(sobj.ObjectId, OpenMode.ForRead, False), Entity) Dim blk As BlockReference = TryCast(ent, BlockReference) If blk IsNot Nothing Then ed.WriteMessage(vbLf & "Block Name: {0}", blk.Name) End If Dim circ As Circle = TryCast(ent, Circle) If circ IsNot Nothing Then ed.WriteMessage(vbLf & "Radius: {0}", circ.Radius.ToString()) End If Dim pline As Polyline = TryCast(ent, Polyline) If pline IsNot Nothing Then ed.WriteMessage(vbLf & "Number Of Vertices: {0}", pline.NumberOfVertices.ToString()) End If Dim ln As Line = TryCast(ent, Line) If ln IsNot Nothing Then ed.WriteMessage(vbLf & "Start Point: {0}", ln.StartPoint.ToString()) End If Next tr.Commit() Catch ex As System.Exception ed.WriteMessage(ex.StackTrace & vbLf & ex.StackTrace) End Try End Using End Sub
Hi,
I'm not sure to understand what you mean with "using Linq".
If you meant using Linq to avoid using a selection set (e.g. using from a side database), her's an example:
Query syntax:
private ObjectId[] FindBlockReferencesInRectangle(Point3d pt1, Point3d pt2, Database db) { using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction()) using (Line line = new Line(pt1, pt2)) { Extents3d bound = line.GeometricExtents; BlockTableRecord modelSpace = (BlockTableRecord)tr.GetObject( SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead); Func<ObjectId, bool> isBlockReference = (id => id.ObjectClass == RXClass.GetClass(typeof(BlockReference))); Func<ObjectId, bool> isInside = (id => { BlockReference br = (BlockReference)tr.GetObject(id, OpenMode.ForRead); Extents3d exts = new Extents3d(bound.MinPoint, bound.MaxPoint); exts.AddExtents(br.GeometricExtents); return bound.IsEqualTo(exts); }); ; var blocks = from ObjectId id in modelSpace where isBlockReference(id) && isInside(id) select id; return blocks.ToArray(); } }
Extension methods syntax:
private ObjectId[] FindBlockReferencesInRectangle(Point3d pt1, Point3d pt2, Database db) { using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction()) using (Line line = new Line(pt1, pt2)) { Extents3d bound = line.GeometricExtents; BlockTableRecord modelSpace = (BlockTableRecord)tr.GetObject( SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead); Func<ObjectId, bool> isBlockReference = (id => id.ObjectClass == RXClass.GetClass(typeof(BlockReference))); Func<ObjectId, bool> isInside = (id => { BlockReference br = (BlockReference)tr.GetObject(id, OpenMode.ForRead); Extents3d exts = new Extents3d(bound.MinPoint, bound.MaxPoint); exts.AddExtents(br.GeometricExtents); return bound.IsEqualTo(exts); }); return modelSpace .Cast<ObjectId>() .Where(isBlockReference) .Where(isInside) .ToArray(); } }
Hi swaywood,
I'm glad it helps.
I also like the functional style available with Linq for the .NET "historic" languages (VB and C#), it is the "natural" way of coding with F#:
let findBlocksInRectangle pt1 pt2 (db : Database) = use tr = db.TransactionManager.StartOpenCloseTransaction() use line = new Line(pt1, pt2) let bound = line.GeometricExtents let rxc = RXClass.GetClass(typeof<BlockReference>) let isBlock (id : ObjectId) = id.ObjectClass = rxc let isInside (id : ObjectId) = let br = tr.GetObject(id, OpenMode.ForRead) :?> BlockReference let exts = new Extents3d(bound.MinPoint, bound.MaxPoint) exts.AddExtents(br.GeometricExtents) exts.IsEqualTo(bound) (tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead) :?> BlockTableRecord) |> Seq.cast<ObjectId> |> Seq.filter isBlock |> Seq.filter isInside |> Seq.toArray
Anyway all these functions do scan the whole model space entities to get all the block references and filter those which are inside the rectangle.
They are all absolutely equivalent to the following one written in a classic imperative style:
private ObjectId[] FindBlockReferencesInRectangle(Point3d pt1, Point3d pt2, Database db) { return QueryForBlocksInRectangle(pt1, pt2, db).ToArray(); } private IEnumerable<ObjectId> QueryForBlocksInRectangle(Point3d pt1, Point3d pt2, Database db) { using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction()) using (Line line = new Line(pt1, pt2)) { Extents3d bound = line.GeometricExtents; RXClass brClass = RXClass.GetClass(typeof(BlockReference)); BlockTableRecord modelSpace = (BlockTableRecord)tr.GetObject( SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead); foreach (ObjectId id in modelSpace) { if (id.ObjectClass == brClass) { BlockReference br = (BlockReference)tr.GetObject(id, OpenMode.ForRead); Extents3d exts = new Extents3d(bound.MinPoint, bound.MaxPoint); exts.AddExtents(br.GeometricExtents); if (bound.IsEqualTo(exts)) { yield return id; } } } } }