Hi,
Here is attempt and although it may not look that professional but works as expected.
Any comments are welcome and I am open to ideas.
[CommandMethod("Foo")] public static void IterateThroughPaperSpaces () { Document Doc = App.DocumentManager.MdiActiveDocument; Editor ed = Doc.Editor; Database db = Doc.Database; PromptEntityOptions ent = new PromptEntityOptions("\nPick on Single polyline: "); ent.SetRejectMessage("\nMust select Single polyline !"); ent.AddAllowedClass(typeof(Polyline), true); ent.AllowNone = false; PromptEntityResult rst = ed.GetEntity(ent); if (rst.Status != PromptStatus.OK) return; using (var tr = db.TransactionManager.StartTransaction()) { TypedValue[] tv = { new TypedValue(0, "INSERT"), new TypedValue(410 , App.GetSystemVariable("CTAB")) }; PromptSelectionResult sel = ed.SelectAll(new SelectionFilter(tv)); var dis = 0.0; double pos = 0.0; ObjectIdCollection objs = new ObjectIdCollection(); Point3d pt = rst.PickedPoint; if (sel.Value == null) { ed.WriteMessage("\nNo Blocks found in this drawing !"); return; } foreach (ObjectId item in sel.Value.GetObjectIds()) { var blk = (BlockReference)tr.GetObject(item, OpenMode.ForRead); if (blk != null) { if (objs.Count < 1) pos = blk.Position.DistanceTo(pt); dis = blk.Position.DistanceTo(pt); if (dis <= pos) { pos = dis; objs.Clear(); objs.Add(item); } } } if (objs.Count > 0) { ObjectId[] ids = new ObjectId[objs.Count]; objs.CopyTo(ids, 0); ed.SetImpliedSelection(ids); } tr.Commit(); }
Hi,
I'm not certain to exactly understand the request, but you probably can get some inspiration from the following snippets.
Get the the closest block reference Id to the specified point in the current space:
private ObjectId GetClosestBlockReferenceId(Point3d point) { var brId = ObjectId.Null; var db = HostApplicationServices.WorkingDatabase; var brClass = RXObject.GetClass(typeof(BlockReference)); using (var tr = db.TransactionManager.StartOpenCloseTransaction()) { var curSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForRead); var query = curSpace.Cast<ObjectId>().Where(id => id.ObjectClass == brClass); if (query.Any()) brId = query .Select(id => (BlockReference)tr.GetObject(id, OpenMode.ForRead)) .Aggregate((br1, br2) => br1.Position.DistanceTo(point) < br2.Position.DistanceTo(point) ? br1 : br2) .ObjectId; tr.Commit(); } return brId; }
Get the closest the closest block reference to the polyline (have to be called form within a transaction):
private ObjectId GetClosestBlockReferenceId(Polyline pline) { var tr = pline.Database.TransactionManager.TopTransaction; var brId = ObjectId.Null; var brClass = RXObject.GetClass(typeof(BlockReference)); var space = (BlockTableRecord)tr.GetObject(pline.OwnerId, OpenMode.ForRead); var query = space.Cast<ObjectId>().Where(id => id.ObjectClass == brClass); if (query.Any()) { brId = query .Select(id => (BlockReference)tr.GetObject(id, OpenMode.ForRead)) .Aggregate((br1, br2) => br1.Position.DistanceTo(pline.GetClosestPointTo(br1.Position, false)) < br2.Position.DistanceTo(pline.GetClosestPointTo(br1.Position, false)) ? br1 : br2) .ObjectId; } return brId; }
Hi
when I select Polyline (2) then I select block close to Polyline (1)
how can I select block inside 5 meters from mouse click so when the block is missing inside 5 meter radius I get warning
Thanks
Sgear
Public Sub inntext() Class_keep_string.popupstring = "" Dim Doc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument Dim ed As Editor = Doc.Editor Dim db As Database = Doc.Database Dim ent As New PromptEntityOptions(vbLf & Class_keep_string.popupstring & " Select Polyline close to Block: ") ent.SetRejectMessage(vbLf & "this is not Polyline !") ent.AddAllowedClass(GetType(Polyline), True) ent.AllowNone = True While True ent.Message = Class_keep_string.popupstring & vbLf & " <--- Select Polyline close to Block: " Dim rst As PromptEntityResult = ed.GetEntity(ent) If rst.Status = PromptStatus.None Then Exit While End If If rst.Status <> PromptStatus.OK Then Return End If ' Using trx As Transaction = db.TransactionManager.StartTransaction() Using tr = db.TransactionManager.StartTransaction() Dim tv As TypedValue() = {New TypedValue(0, "INSERT"), New TypedValue(410, Autodesk.AutoCAD.ApplicationServices.Application.GetSystemVariable("CTAB"))} Dim sel As PromptSelectionResult = ed.SelectAll(New SelectionFilter(tv)) Dim dis = 0.0 Dim pos As Double = 0.0 Dim objs As New ObjectIdCollection() Dim pt As Point3d = rst.PickedPoint If sel.Value Is Nothing Then ed.WriteMessage(vbLf & "No block!") Return End If For Each item As ObjectId In sel.Value.GetObjectIds() Dim blk = CType(tr.GetObject(item, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForRead), BlockReference) If blk IsNot Nothing Then If objs.Count < 1 Then pos = blk.Position.DistanceTo(pt) End If dis = blk.Position.DistanceTo(pt) If dis <= pos Then pos = dis objs.Clear() objs.Add(item) ed.WriteMessage(vbLf & dis.ToString) ed.WriteMessage(vbLf & pos.ToString) End If End If Next If objs.Count > 0 Then Dim ids As ObjectId() = New ObjectId(objs.Count - 1) {} objs.CopyTo(ids, 0) Dim ent2 As Entity ent2 = TryCast(tr.GetObject(objs.Item(0), Autodesk.AutoCAD.DatabaseServices.OpenMode.ForWrite), Entity) 'If pos >= 4.19796655251786 Then 'Else ' ent2.ColorIndex = "3" 'End If End If tr.Commit() End Using End While ' End Using End Sub
Hi,
Perhaps you can get some inspiration from this method using Linq to get the closest block reference to a specified point within a distance (if any).
private BlockReference SelectClosestBlockWihinRadius(Point3d center, double radius, BlockTableRecord space) { return space .Cast<ObjectId>() .Where(id => id.ObjectClass.DxfName == "INSERT") .Select(id => (BlockReference)id.GetObject(OpenMode.ForRead)) .Where(br => br.Position.DistanceTo(center) < radius) .OrderBy(br => br.Position.DistanceTo(center)) .FirstOrDefault(); }
using example:
using (var tr = db.TransactionManager.StartTransaction()) { var curSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForRead); var br = SelectClosestBlockWihinRadius(center, 5.0, curSpace); if (br != null) { br.UpgradeOpen(); br.ColorIndex = 3; } tr.Commit(); }
Imperative way:
private BlockReference SelectClosestBlockWihinRadius(Point3d center, double radius, BlockTableRecord space) { BlockReference result = null; foreach (ObjectId id in space) { if (id.ObjectClass.DxfName == "INSERT") { var br = (BlockReference)id.GetObject(OpenMode.ForRead); double dist = br.Position.DistanceTo(center); if (dist < radius) { result = br; radius = dist; } } } return result; }
Thanks
I try to use http://converter.telerik.com/ to convert to VB.NET
Dim br = SelectClosestBlockWihinRadius(center, 5.0, curSpace)
'center' is not declared. It may be inaccessible due to its protection level.
Using tr = db.TransactionManager.StartTransaction() Dim curSpace = DirectCast(tr.GetObject(db.CurrentSpaceId, OpenMode.ForRead), BlockTableRecord) Dim br = SelectClosestBlockWihinRadius(center, 5.0, curSpace) If br IsNot Nothing Then br.UpgradeOpen() br.ColorIndex = 3 End If tr.Commit() End Using Private Function SelectClosestBlockWihinRadius(center As Point3d, radius As Double, space As BlockTableRecord) As BlockReference Dim result As BlockReference = Nothing For Each id As ObjectId In space If id.ObjectClass.DxfName = "INSERT" Then Dim br = DirectCast(id.GetObject(OpenMode.ForRead), BlockReference) Dim dist As Double = br.Position.DistanceTo(center) If dist < radius Then result = br radius = dist End If End If Next Return result End Function
That was just one example.
'center' is the center (Point3d) of the circle in which you are looking for a block. IOW, if I understand what you are trying to do: the picked point from which you are looking for a block at 5 meters maximum.
EDIT:
From the code you posted:
Dim center As Point3d = rst.PickedPoint.TransformBy(ed.CurrentCoordinateSystem)
Finish to fix this and works well
Yes I am tray to do this "looking for a block at 5 meters maximum from Point3d."
Thanks _gile for your help !
Dim br = SelectClosestBlockWihinRadius(rst.PickedPoint, 5.0, curSpace)
Regards
Sgear