• Industries
  • Products
  • Buy
  • Services & Support
  • Communities
  • Discussion Groups

    .NET

    Reply
    Member
    Posts: 5
    Registered: ‎05-24-2012

    How to locate text near blockreference

    240 Views, 8 Replies
    05-24-2012 07:27 PM

    I have tried to use intersectwith to locate text (MText or DBText) near a block reference. Some times it works and some times it does not. The hard part for me is understanding why it occasionally works when most examples are just duplicates with modified text and attributes.

     

    My block reference has 4 attributes  to the left (Right Justified) of a circle and 2 attributes inside the circle. The text objects are used by some CAD operators instead of the upper 2 lines of attributtes. (Guess they dont know how to modify attributes) I want to locate these texts and insert text into the corresponding attribute.

     

    Block Reference:

     

    Att 1   |'''''''|  <-- CAD User will insert a txt over Att 1 and Att 2, 

    Att 2  |       | <--  both attributes are usally left blank or contain a space

    Att 3  |       |

    Att 4   |.....|

    Please use plain text.
    *Expert Elite*
    Posts: 6,432
    Registered: ‎06-29-2007

    Re: How to locate text near blockreference

    05-24-2012 11:39 PM in reply to: darrell.caldwell

    Hi,

     

    >> intersectwith to locate text (MText or DBText) near a block reference

    Can you show the code that does what you described with this sentence? Because IntersectWith needs exact geometry and not "near to" any geom.

    If you are working with geometric extents from your attribute-values then be careful, sometimes the extents of AttributeReferences are calculated wrong (the min- or max-point of the extents points to 0,0,0). If you use COM-GetBoundingBox it works.

    Also if the AttributeReferences have no text in .TextString you may (you will) have difficulties with IntersectWith.


    Show the code that does not do what you want to have and also upload a drawing for that situation. That will help us (and you) to come faster to a solution (hopefully :smileywink: )

     

    - alfred -

    -------------------------------------------------------------------------
    Alfred NESWADBA
    Ingenieur Studio HOLLAUS ... www.hollaus.at
    -------------------------------------------------------------------------
    Please use plain text.
    Member
    Posts: 5
    Registered: ‎05-24-2012

    Re: How to locate text near blockreference

    05-25-2012 07:53 PM in reply to: alfred.neswadba

    alfred,

     

    Thanks for the quick response. I left my laptop at work and all the code is there and I will not be back till Teusday. If I remember correctly my statement looks something like this,

     

    ******************************************************

    .... some code ....

    myAttributeReference.TextString = "XXXXXXXX"

    .... some code ....

    Dim colInters As New Point3dCollection


    myAttributeReference.IntersectWith(myMText, Intersect.OnBothOperands, colIntrs, 0, 0)

    .... some code ....

    ******************************************************

    Out of curiosity, which way would you attempt to locate MText or DBText arranged as stated.

     

    Please use plain text.
    *Expert Elite*
    Posts: 6,432
    Registered: ‎06-29-2007

    Re: How to locate text near blockreference

    05-28-2012 12:36 PM in reply to: darrell.caldwell

    Hi,

     

    >> Out of curiosity, which way would you attempt to locate MText or DBText arranged as stated

    I did not yet check intersections of text-like objects. What I would do (just one idea) is to create a line in the mid of the text-height (and the angle of the text and check then if the lines intersect.

     

    - alfred -

    -------------------------------------------------------------------------
    Alfred NESWADBA
    Ingenieur Studio HOLLAUS ... www.hollaus.at
    -------------------------------------------------------------------------
    Please use plain text.
    Member
    Posts: 5
    Registered: ‎05-24-2012

    Re: How to locate text near blockreference

    05-29-2012 12:06 PM in reply to: darrell.caldwell

    OK,

    here is the code and I have attached a drawing with examples.

    I rewrote the code to draw a polyline around the geometricextents of the BlockReference. Then itereate all TEXT or MTEXT object in model space and check for intersects.

     

    I have the origianl blockreference that I am working with, run "DPL" to text the code. it should draw a polyline within the extents of the blockreference. Then attempt to check intersects with the MTEXT object right next to it. It want find any, although it should.

     

    Example two, is the smaller polyline with MTEXT object on top of it. Type "inters" and you will see that intersections exist. These objects where drawn manually using normal polyline and mtext commands.

     

    Example three is the larger polyline with the MTEXT object on top. Type "inters" and you will see that no intersections exist. The polyline was drawn by code from the "DPL" command. So, my code drawn polyline does not intersect with the MTEXT variable.

     

    Why not. ????

     

    Option Explicit On
    Option Strict On

    Imports Autodesk.AutoCAD.Runtime
    Imports Autodesk.AutoCAD.DatabaseServices
    Imports Autodesk.AutoCAD.ApplicationServices
    Imports Autodesk.AutoCAD.EditorInput
    Imports Autodesk.AutoCAD.Geometry
    Imports Autodesk.AutoCAD.Colors

    Imports System.IO
    Imports Microsoft.Win32
    Imports System.Reflection

    Public Class Class1

    <CommandMethod("inters", CommandFlags.UsePickSet)> _
    Public Sub GetInters()
    Dim doc As Document = Application.DocumentManager.MdiActiveDocument
    Dim db As Database = doc.Database

    Dim ed As Editor = doc.Editor
    Dim tr As Transaction = db.TransactionManager.StartTransaction
    Try
    Using tr
    Dim acBT As BlockTable = CType(tr.GetObject(db.BlockTableId, OpenMode.ForRead), BlockTable)
    Dim acMS As BlockTableRecord = CType(tr.GetObject(acBT(BlockTableRecord.ModelSpace), OpenMode.ForRead), BlockTableRecord)
    Dim opt As New PromptEntityOptions(vbLf & "Select entity: ")
    opt.SetRejectMessage(vbLf & "Error selecting entity")
    opt.AllowNone = False
    'opt.AddAllowedClass(GetType(BlockReference), True)
    Dim res As PromptEntityResult = ed.GetEntity(opt)
    If res.Status <> PromptStatus.OK Then Return
    Dim lid As ObjectId = res.ObjectId
    opt = New PromptEntityOptions(vbLf & "Select entity: ")
    opt.SetRejectMessage(vbLf & "Error selecting entity")
    'opt.AddAllowedClass(GetType(MText), True)
    'opt.AddAllowedClass(GetType(DBText), True)
    res = ed.GetEntity(opt)
    If res.Status <> PromptStatus.OK Then Return
    Dim pid As ObjectId = res.ObjectId
    Dim pts As Point3dCollection = New Point3dCollection()
    ed.WriteMessage(vbLf & "{0} <> {1};", lid, pid)
    Dim ent1 As Entity = CType(tr.GetObject(lid, OpenMode.ForRead), Entity)
    Dim ent2 As Entity = TryCast(tr.GetObject(pid, OpenMode.ForRead), Entity)

    'Dim plane As Plane = New Plane(ed.CurrentUserCoordinateSystem.CoordinateSystem3d.Origin, ed.CurrentUserCoordinateSystem.CoordinateSystem3d.Zaxis)
    'ent1.IntersectWith(ent2, Intersect.OnBothOperands, Plane, pts, 0, 0)
    ent1.IntersectWith(ent2, Intersect.OnBothOperands, pts, 0, 0)
    ed.WriteMessage(vbLf & "Number of intersections: {0}", pts.Count)

    Dim i As Integer = 1
    For Each pt As Point3d In pts
    ed.WriteMessage(vbLf & "Point number {0}: ({1}, {2}, {3})", i, pt.X, pt.Y, pt.Z)
    i += 1
    Next
    tr.Commit()
    End Using
    Catch ex As Autodesk.AutoCAD.Runtime.Exception
    ed.WriteMessage(vbLf & "{0}", ex.Message)
    End Try
    End Sub

    ''' <summary>
    ''' Draws a box around the extents of selected object
    ''' </summary>
    ''' <remarks></remarks>
    <CommandMethod("DPL", CommandFlags.UsePickSet)> _
    Public Sub DrawPolyLine()
    Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
    Dim acDB As Database = acDoc.Database

    Dim acDocEd As Editor = acDoc.Editor
    Dim tr As Transaction = acDB.TransactionManager.StartTransaction
    Try
    Using tr
    Dim acBT As BlockTable = CType(tr.GetObject(acDB.BlockTableId, OpenMode.ForRead), BlockTable)
    Dim acMS As BlockTableRecord = CType(tr.GetObject(acBT(BlockTableRecord.ModelSpace), OpenMode.ForRead), BlockTableRecord)
    Dim opt As New PromptEntityOptions(vbLf & "Select block: ")
    opt.SetRejectMessage(vbLf & "Only Block Reference allowed...")
    opt.AllowNone = False
    opt.AddAllowedClass(GetType(BlockReference), True)

    Dim res As PromptEntityResult = acDocEd.GetEntity(opt)
    If res.Status <> PromptStatus.OK Then Return

    Dim blkID As ObjectId = res.ObjectId
    Dim acAttID As ObjectId
    Dim acBlkRef As BlockReference = CType(tr.GetObject(blkID, OpenMode.ForRead), BlockReference)
    Dim acAttRef As New AttributeReference
    Dim strAttTemp As String = ""
    Dim attIDs As AttributeCollection = acBlkRef.AttributeCollection
    For Each attID As ObjectId In attIDs
    acAttRef = CType(tr.GetObject(attID, OpenMode.ForRead), AttributeReference)
    If acAttRef.Tag = "1" Then
    acAttID = attID
    strAttTemp = acAttRef.TextString
    acAttRef.UpgradeOpen()
    acAttRef.TextString = "XXXXXXXXXX"
    acAttRef.DowngradeOpen()
    End If
    Next

    Dim ext3D As Extents3d = acBlkRef.GeometricExtents
    Dim dWidth As Double = (ext3D.MaxPoint.Y - ext3D.MinPoint.Y)
    Dim plStartPnt As Point2d = New Point2d(ext3D.MinPoint.X, ext3D.MinPoint.Y + dWidth / 2)
    Dim plEndPnt As Point2d = New Point2d(ext3D.MaxPoint.X, ext3D.MinPoint.Y + dWidth / 2)
    Dim pl As Polyline = New Polyline
    pl.AddVertexAt(0, plStartPnt, 0, dWidth, dWidth)
    pl.AddVertexAt(0, plEndPnt, 0, dWidth, dWidth)

    'If acAttRef IsNot Nothing Then
    acAttRef.UpgradeOpen()
    acAttRef.TextString = strAttTemp
    acAttRef.DowngradeOpen()
    'End If

    acMS.UpgradeOpen()
    acMS.AppendEntity(pl)
    tr.AddNewlyCreatedDBObject(pl, True)
    acMS.DowngradeOpen()
    acDocEd.Regen()

    '' Create a TypedValue array to define the filter criteria of Text or MText
    Dim acTypValAr(3) As TypedValue
    acTypValAr.SetValue(New TypedValue(DxfCode.Operator, "<or"), 0)
    acTypValAr.SetValue(New TypedValue(DxfCode.Start, "TEXT"), 1)
    acTypValAr.SetValue(New TypedValue(DxfCode.Start, "MTEXT"), 2)
    acTypValAr.SetValue(New TypedValue(DxfCode.Operator, "or>"), 3)
    '' Assign the filter criteria to a SelectionFilter object
    Dim acSelFtr As SelectionFilter = New SelectionFilter(acTypValAr)
    '' Request for objects to be selected in the drawing area
    Dim acSSPrompt As PromptSelectionResult
    acSSPrompt = acDocEd.SelectAll(acSelFtr)
    '' If the prompt status is OK, objects were selected
    If acSSPrompt.Status = PromptStatus.OK Then
    Dim acSSet As SelectionSet = acSSPrompt.Value
    Dim acObjIDs As ObjectId() = acSSet.GetObjectIds
    For Each acObjID As ObjectId In acObjIDs
    If acObjID.ObjectClass.Name = "AcDbText" Then
    Dim acText As DBText = CType(tr.GetObject(acObjID, OpenMode.ForRead), DBText)
    Dim colPnts As New Point3dCollection
    pl.IntersectWith(CType(acText, Entity), Intersect.OnBothOperands, colPnts, 0, 0)
    If colPnts.Count > 0 Then
    acDocEd.WriteMessage(acText.TextString)
    End If
    Else
    Dim acMText As MText = CType(tr.GetObject(acObjID, OpenMode.ForRead), MText)
    Dim colPnts As New Point3dCollection
    pl.IntersectWith(CType(acMText, Entity), Intersect.OnBothOperands, colPnts, 0, 0)
    If colPnts.Count > 0 Then
    acDocEd.WriteMessage(acMText.Text)
    End If
    End If
    Next

    End If

    tr.Commit()
    End Using
    Catch ex As Autodesk.AutoCAD.Runtime.Exception
    acDocEd.WriteMessage(vbLf & "{0}", ex.Message)
    End Try
    End Sub

    End Class

    Please use plain text.
    *Expert Elite*
    Posts: 6,432
    Registered: ‎06-29-2007

    Re: How to locate text near blockreference

    05-29-2012 10:58 PM in reply to: darrell.caldwell

    Hi,

     

    Example 1:

    >> Then attempt to check intersects with the MTEXT object right next to it. It want find any, although it should.

    If I run your DPL-Code (with AutoCAD 2010 currently) I get a polyline as one result and I get the AttributeReference "1" filled with "XXXXXXXXXX"

    So isn't that working as it should be?

     

    Example 2:

    I see 4 intersections and also 4 points if intersections listed

     

    Example 3:

    I see also 4 intersections and also 4 points listed

     

     

    I think the next question is: what AutoCAD release (and may be what vertical product) are you using that does not return the same results at your system?

     

    And just one shortening to your code :smileywink:

     

    Dim acTypValAr() As TypedValue = {New TypedValue(DxfCode.Start, "TEXT,MTEXT")}

     to be used for filtering a selectionset to TEXT or MTEXT objects.

     

    - alfred -

    -------------------------------------------------------------------------
    Alfred NESWADBA
    Ingenieur Studio HOLLAUS ... www.hollaus.at
    -------------------------------------------------------------------------
    Please use plain text.
    Member
    Posts: 5
    Registered: ‎05-24-2012

    Re: How to locate text near blockreference

    05-30-2012 06:55 AM in reply to: darrell.caldwell

    Thanks Alfred,

     

    Question, will this work using your shortening example

     

    Dim acTypValAr() As TypedValue = {New TypedValue(DxfCode.Start, "TEXT,MTEXT"), New TypedValue(DxfCode.LayerName, "GEN_TEXT_RU,CPC_TEXT")}

     

    to replace the following

     

    Dim acTypValAr(9) As TypedValue
    acTypValAr.SetValue(New TypedValue(DxfCode.Operator, "<and"), 0)
    acTypValAr.SetValue(New TypedValue(DxfCode.Operator, "<or"), 1)
    acTypValAr.SetValue(New TypedValue(DxfCode.Start, "TEXT"), 2)
    acTypValAr.SetValue(New TypedValue(DxfCode.Start, "MTEXT"), 3)
    acTypValAr.SetValue(New TypedValue(DxfCode.Operator, "or>"), 4)
    acTypValAr.SetValue(New TypedValue(DxfCode.Operator, "<or"), 5)
    acTypValAr.SetValue(New TypedValue(DxfCode.LayerName, "GEN_TEXT_RU"), 6)
    acTypValAr.SetValue(New TypedValue(DxfCode.LayerName, "CPC_TEXT"), 7)
    acTypValAr.SetValue(New TypedValue(DxfCode.Operator, "or>"), 8)
    acTypValAr.SetValue(New TypedValue(DxfCode.Operator, "and>"), 9)

    Please use plain text.
    *Expert Elite*
    Posts: 6,432
    Registered: ‎06-29-2007

    Re: How to locate text near blockreference

    05-30-2012 06:57 AM in reply to: darrell.caldwell

    Hi,

     

    >> will this work using your shortening example

    Yes, but I think you would have tried/verified it faster than asked here :smileywink:

     

    - alfred -

    -------------------------------------------------------------------------
    Alfred NESWADBA
    Ingenieur Studio HOLLAUS ... www.hollaus.at
    -------------------------------------------------------------------------
    Please use plain text.
    Member
    Posts: 5
    Registered: ‎05-24-2012

    Re: How to locate text near blockreference

    05-30-2012 07:31 AM in reply to: darrell.caldwell

    Back on track,

    I am using AutoCAD Mechanical 2010

     

    Command "DPL" does the following,

    gets blockreference from user,

    changes attRef1 text to "XXXXXXXXXX" ( this will assist in extending the geometricextents)

    draws a polyline inside the geometric extents of the blockreference

    iterate thru all MTEXT or TEXT objects looking for intersections if any are found, write its text to the editor

     

    When I run it, the text is changed, polyline is drawn but no intersections are found.

     

    On example 3, I determined that if I move the MTEXT down slightly, then it will return an intersection, but left at its current position it does not work (on my system). I am stumbed as to why it works on yours.

     

    My assumption is that the polyline only compares intersection with the centerline if its width, not with the boundry of the object. In regards to this, I have rewritten my code to draw polyline with no width that zig-zags across the geometricextents of the block and then checks for intersections. So far this seems to be working.

     

    I will post the code shortly.

     

    Please use plain text.