Jump to content

Get MText Inside Block Reference


Recommended Posts

Posted

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.

Posted

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)
 )

Posted
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();
       }
   }
}

Posted

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.

Posted

Hi BlackBox

 

Thank you for your help.

I will try your code and feed back.

 

Thanks

Posted

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.

Posted

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.

Posted

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

Posted

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

Posted
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.

Posted
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.

Posted

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.

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...