OmarSuliman Posted January 8, 2015 Posted January 8, 2015 Hi All; I need to search for all Mtext (Inside) a Block Reference. I worked and searched hard on this, but no result. Any help please, it is very necessary for me. Thanks in advance. Quote
fuccaro Posted January 8, 2015 Posted January 8, 2015 Hello! You posted your request in the DotNet forum... I can help you only with a Lisp solution. Here you are: (defun c:FindMT() (setq bl (tblnext "BLOCK" 1)) (while bl (setq name (cdr (assoc 2 bl)) mt nil) (princ (strcat "\n\n == Block: " name " ==")) (setq ent (tblobjname "BLOCK" name)) (while ent (setq ent (entnext ent)) (if ent (progn (setq el (entget ent)) (if (= "MTEXT" (cdr (assoc 0 el))) (progn (setq mt 1) (princ (strcat "\n" (cdr (assoc 1 el)))) ) ) ) ) ) (if (not mt) (princ " >> no MTEXT")) (setq bl (tblnext "BLOCK")) ) (princ) ) Quote
BlackBox Posted January 8, 2015 Posted January 8, 2015 Hi All; I need to search for all Mtext (Inside) a Block Reference. I worked and searched hard on this, but no result. Any help please, it is very necessary for me. BlockReference is just a graphical representation of its parent Block Definition (aka BlockTableRecord). This should get you started (C#): // using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Runtime; using acApp = Autodesk.AutoCAD.ApplicationServices.Application; [assembly: CommandClass(typeof(FOO.Commands))] namespace FOO { public class Commands { private static DocumentCollection acDocs = acApp.DocumentManager; [CommandMethod("FOO")] public void FOO() { Document doc = acDocs.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; SelectionFilter sf = new SelectionFilter( new TypedValue[1] { new TypedValue(0, "INSERT") }); PromptSelectionOptions pso = new PromptSelectionOptions(); pso.MessageForAdding = "Select block references:"; PromptSelectionResult psr = ed.GetSelection(pso, sf); if (psr.Status != PromptStatus.OK) { ed.WriteMessage("\n** Nothing selected ** \n"); return; } dynamic acDoc = doc.GetAcadDocument(); acDoc.StartUndoMark(); using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction()) { ObjectIdCollection ids = new ObjectIdCollection(); foreach (ObjectId id in psr.Value.GetObjectIds()) { BlockReference br = (BlockReference)tr.GetObject(id, OpenMode.ForRead); ObjectId btrId = br.BlockTableRecord; if (!ids.Contains(btrId)) { ids.Add(btrId); BlockTableRecord btr = (BlockTableRecord)tr.GetObject(btrId, OpenMode.ForWrite); foreach (ObjectId bid in btr) { MText mtext = tr.GetObject(bid, OpenMode.ForRead) as MText; if (mtext != null) { mtext.UpgradeOpen(); mtext.ColorIndex = 1; mtext.DowngradeOpen(); } } } } tr.Commit(); } ed.Regen(); acDoc.EndUndoMark(); } } } Quote
OmarSuliman Posted January 9, 2015 Author Posted January 9, 2015 Hi fuccaro I really thank you for your help, i don't know any thing about lisp, so i tried to convert your code to .net code but i did not find any convertor doing that. thank you too much. Quote
OmarSuliman Posted January 9, 2015 Author Posted January 9, 2015 Hi BlackBox Thank you for your help. I will try your code and feed back. Thanks Quote
fuccaro Posted January 9, 2015 Posted January 9, 2015 No conversion needed. See this old link: http://www.cadtutor.net/forum/showthread.php?1390-How-to-use-the-LISP-routines-in-this-archive Follow just CADTutor's instyructions from the first post in that thread. Good luck! Quote
OmarSuliman Posted January 9, 2015 Author Posted January 9, 2015 Hi BlackBox I tested your code, it works good. It discovers if the (Mtext) is one of the (components) of the (BlockReference) or no. But i need to search for (MText) that (resides) inside the block reference In other words, the block reference in my case is a (container) or (area) or (region) and the Mtext is inside it. any help please. Thank you. Quote
SEANT Posted January 9, 2015 Posted January 9, 2015 It sounds like you are trying to find an Mtext entity in Model Space that has a GeometricExtents (or perhaps just Insertion point) located within the GeometricExtents of a BlockReference. It may be helpful to post a sample drawing file containing the same general scenario that you are trying to process. Quote
OmarSuliman Posted January 10, 2015 Author Posted January 10, 2015 Thank you fuccaro, i will try this way. Quote
OmarSuliman Posted January 10, 2015 Author Posted January 10, 2015 Hi SEANT Thank you for your help i am working on two different pieces of code First one is finding if the point inside the polygon,it is working fine, i tried to convert the code to achieve my needs but i failed till now <CommandMethod("TEST")> _ Public Sub Test() Dim doc As Document = Application.DocumentManager.MdiActiveDocument Dim db As Database = doc.Database Dim ed As Editor = doc.Editor Dim peo As New PromptEntityOptions(vbLf & "Select a polyline: ") peo.SetRejectMessage("Only a polyline !") peo.AddAllowedClass(GetType(Polyline), True) Dim per As PromptEntityResult = ed.GetEntity(peo) If per.Status <> PromptStatus.OK Then Return End If Using tr As Transaction = db.TransactionManager.StartOpenCloseTransaction() Dim pline As Polyline = DirectCast(tr.GetObject(per.ObjectId, OpenMode.ForRead), Polyline) If Not pline.Closed Then ed.WriteMessage(vbLf & "Polyline must be closed.") Return End If Dim curves As New DBObjectCollection() curves.Add(pline) Try Using regions As DBObjectCollection = Region.CreateFromCurves(curves) Using region__1 As Region = DirectCast(regions(0), Region) Dim ppo As New PromptPointOptions(vbLf & "Pick a point <quit>: ") ppo.AllowNone = True While True Dim ppr As PromptPointResult = ed.GetPoint(ppo) If ppr.Status <> PromptStatus.OK Then Exit While End If Application.ShowAlertDialog(GetPointContainment(region__1, ppr.Value).ToString()) End While End Using End Using Catch exn As System.Exception ed.WriteMessage(vbLf & "Error: " & exn.Message) End Try End Using End Sub Private Function GetPointContainment(region As Region, point As Point3d) As PointContainment Dim result As PointContainment = PointContainment.Outside Using brep As New Brep(region) If brep IsNot Nothing Then Using ent As BrepEntity = brep.GetPointContainment(point, result) If TypeOf ent Is Autodesk.AutoCAD.BoundaryRepresentation.Face Then result = PointContainment.Inside End If End Using End If End Using Return result End Function Quote
OmarSuliman Posted January 10, 2015 Author Posted January 10, 2015 Second one is finding if the point is inside or out side the region object, also i tried with it. Namespace BRepSamples Public NotInheritable Class Containment Private Sub New() End Sub '' <summary> '' '' This sample shows how to use the BREP API to do '' simple topographical point/boundary classification '' on regions. '' '' This code requires a reference to AcDbMgdBrep.dll '' '' The sample prompts for a region object; gets a BRep '' object representing the region; and then repeatedly '' prompts for points, and computes and displays the '' containment (inside, outside, or on an edge) of each '' selected point. '' '' A point within an inner loop is considered to be '' 'ouside' the region's area, and so if you perform '' this operation on a complex region with inner loops, '' points contained within an inner loop will yield a '' result of PointContainment.Outside. ' '' This is the most robust means of determining if a '' point lies within the implied boundary formed by a '' collection of AutoCAD entites that can be used to '' create a valid AutoCAD Region object, and is the '' preferred means of doing simple point containment '' testing. '' '' You can adapt this code to perform containment tests '' on various AutoCAD entities such as closed polylines, '' splines, ellipses, etc., by generating a region from '' the closed geometry, using it to do the containment '' test, and then disposing it without having to add it '' to a database. '' '' Note that the sample code was designed to work with '' regions that lie in the WCS XY plane and points that '' lie in the same plane. '' '' </summary> <CommandMethod("CONTAINMENT")> _ Public Shared Sub ContainmentCommand() Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor Dim id As ObjectId = GetRegion(ed, vbLf & "Select a region: ") If Not id.IsNull Then Using tr As Transaction = ed.Document.TransactionManager.StartTransaction() Try Dim region As Region = TryCast(id.GetObject(OpenMode.ForRead), Region) Dim ppo As New PromptPointOptions(vbLf & "Select a point: ") ppo.AllowNone = True While True ' loop while user continues to pick points '' Get a point from user: Dim ppr As PromptPointResult = ed.GetPoint(ppo) If ppr.Status <> PromptStatus.OK Then ' no point was selected, exit Exit While End If ' use the GetPointContainment helper method below to ' get the PointContainment of the selected point: Dim containment As PointContainment = GetPointContainment(region, ppr.Value) ' Display the result: ed.WriteMessage(containment.ToString()) End While Finally tr.Commit() End Try End Using End If End Sub '' <summary> '' '' This variation performs point contianment testing '' against any closed curve from which a simple region ' (e.g., no inner-loops) can be genreated, using the '' Region.CreateFromCurves() API. '' '' </summary> <CommandMethod("CURVECONTAINMENT")> _ Public Shared Sub CurveContainmentCommand() Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor Dim id As ObjectId = GetCurve(ed, vbLf & "Select a closed Curve: ") If Not id.IsNull Then Using tr As Transaction = ed.Document.TransactionManager.StartTransaction() Try Dim curve As Curve = DirectCast(id.GetObject(OpenMode.ForRead), Curve) If Not curve.Closed Then ed.WriteMessage(vbLf & "Invalid selection, requires a CLOSED curve") Return End If Using region As Region = RegionFromClosedCurve(curve) Dim ppo As New PromptPointOptions(vbLf & "Select a point: ") ppo.AllowNone = True While True ' loop while user continues to pick points '' Get a point from user: Dim ppr As PromptPointResult = ed.GetPoint(ppo) If ppr.Status <> PromptStatus.OK Then ' no point was selected, exit Exit While End If ' use the GetPointContainment helper method below to ' get the PointContainment of the selected point: Dim containment As PointContainment = GetPointContainment(region, ppr.Value) ' Display the result: ed.WriteMessage(containment.ToString()) End While End Using Finally tr.Commit() End Try End Using End If End Sub ' this helper method takes a Region and a Point3d that must be ' in the plane of the region, and returns the PointContainment ' of the given point, adjusted to correctly indicate its actual ' relationship to the region (inside/on boundary edge/outside). Public Shared Function GetPointContainment(region As Region, point As Point3d) As PointContainment Dim result As PointContainment = PointContainment.Outside '' Get a Brep object representing the region: Using brep As New Brep(region) If brep IsNot Nothing Then ' Get the PointContainment and the BrepEntity at the given point: Using ent As BrepEntity = brep.GetPointContainment(point, result) ' GetPointContainment() returns PointContainment.OnBoundary ' when the picked point is either inside the region's area '' or exactly on an edge. ' '' So, to distinguish between a point on an edge and a point '' inside the region, we must check the type of the returned '' BrepEntity: '' '' If the picked point was on an edge, the returned BrepEntity '' will be an Edge object. If the point was inside the boundary, '' the returned BrepEntity will be a Face object. '' So if the returned BrepEntity's type is a Face, we return '' PointContainment.Inside: If TypeOf ent Is Autodesk.AutoCAD.BoundaryRepresentation.Face Then result = PointContainment.Inside End If End Using End If End Using Return result End Function Public Shared Function RegionFromClosedCurve(curve As Curve) As Region If Not curve.Closed Then Throw New ArgumentException("Curve must be closed.") End If Dim curves As New DBObjectCollection() curves.Add(curve) Using regions As DBObjectCollection = Region.CreateFromCurves(curves) If regions Is Nothing OrElse regions.Count = 0 Then Throw New InvalidOperationException("Failed to create regions") End If If regions.Count > 1 Then Throw New InvalidOperationException("Multiple regions created") End If Return regions.Cast(Of Region)().First() End Using End Function Public Shared Function GetPointContainment(curve As Curve, point As Point3d) As PointContainment If Not curve.Closed Then Throw New ArgumentException("Curve must be closed.") End If Dim region As Region = RegionFromClosedCurve(curve) If region Is Nothing Then Throw New InvalidOperationException("Failed to create region") End If Using region Return GetPointContainment(region, point) End Using End Function Public Shared Function GetCurve(editor As Editor, msg As String) As ObjectId Dim peo As New PromptEntityOptions(msg) peo.SetRejectMessage("Invalid selection: requires a closed Curve,") peo.AddAllowedClass(GetType(Curve), False) Dim res As PromptEntityResult = editor.GetEntity(peo) Return If(res.Status = PromptStatus.OK, res.ObjectId, ObjectId.Null) End Function Public Shared Function GetRegion(editor As Editor, msg As String) As ObjectId Dim peo As New PromptEntityOptions(msg) peo.SetRejectMessage("Invalid selection: requires a region,") peo.AddAllowedClass(GetType(Region), False) Dim res As PromptEntityResult = editor.GetEntity(peo) Return If(res.Status = PromptStatus.OK, res.ObjectId, ObjectId.Null) End Function End Class End Namespace Quote
fuccaro Posted January 10, 2015 Posted January 10, 2015 Thank you fuccaro, i will try this way. It will not work as you expect it... It also searches for Mtexts inside of the block definitions. Quote
OmarSuliman Posted January 11, 2015 Author Posted January 11, 2015 It will not work as you expect it... It also searches for Mtexts inside of the block definitions. No problem, it will be solved . Thank you for your time. Quote
SEANT Posted January 11, 2015 Posted January 11, 2015 I still think you need to post a DWG file illustrating the entities as you expect your routine would find them. Ideally the example file would demonstrate a setup that should pass a the test, as well as a setup that should not. Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.