VBA ABD(SS6) How to Get Start Point and End Point of Cell Element?

Hello All, I'm trying to create a primitive gusset plate routine in VBA to run in AECOsim Building Designer (SS6). I want the VBA routine to draw a 4'x4' box at the start and end of each element (line). Lines in ABD for structural members are actually cells, and as a result, I can't figure out how to get coordinates for the start and endpoint of my "lines". I can only use .StartPoint and .EndPoint when using .AsLineElement, but lines in ABD are .IsCellElement, so I can only use .Origin (I think). Is there any way to get a cell element to use the .AsLineElement callout, or maybe somehow trace a temporary line over the cell to use it's start and end points? I have code that works when I draw simple lines, so I know I'm on the right track. I don't have a lot of experience with VBA and I've been reading the forums, help menu, and google searches for two days, but I just can't work past this. Thanks for any help.

Sub GussetPlates()

'Scan For Horizontal Bracing
Dim StartPoint As Point3d
Dim Point As Point3d, Point2 As Point3d

Dim myCounter As Integer
Dim myElementEnumerator As ElementEnumerator
Dim myScanCriteria As New ElementScanCriteria
Dim myElement As Element

Dim myGussPL As Level
Dim myHB As Level
Dim myVB As Level
Set myHB = ActiveDesignFile.Levels("S-STL-HB")
Set myVB = ActiveDesignFile.Levels("S-STL-VB")
Set myGussPL = ActiveDesignFile.Levels("S-STL-PLAT-GUSS")

Dim myPoints As Point3d
Dim myLine As LineElement
Dim myEndPt As Variant
Dim myStartPt As Variant
Dim myRange As Range3d

myScanCriteria.ExcludeNonGraphical
myScanCriteria.ExcludeAllLevels
myScanCriteria.IncludeLevel myHB


Set myElementEnumerator = ActiveModelReference.Scan(myScanCriteria)
myElementEnumerator.Reset

While myElementEnumerator.MoveNext
    Set myElement = myElementEnumerator.Current
        If myElement.IsCellElement Then
            ActiveSettings.Level = myGussPL
                 
            
            '''THIS IS WHERE I'M STUCK'''
            myStartPt = myElement.AsLineElement.StartPoint
            myEndPt = myElement.AsLineElement.EndPoint
            
            
        CadInputQueue.SendCommand "PLACE SMARTLINE"
 
        'Coordinates are in master units
        StartPoint.X = myStartPt.X
        StartPoint.Y = myStartPt.Y
        StartPoint.Z = myStartPt.Z
 
        'Send a data point to the current command
        Point.X = StartPoint.X
        Point.Y = StartPoint.Y
        Point.Z = StartPoint.Z
        CadInputQueue.SendDataPoint Point, 1
 
        'Send a data point to the current command
        Point.X = StartPoint.X + 4
        Point.Y = StartPoint.Y + 0
        Point.Z = StartPoint.Z + 0
        CadInputQueue.SendDataPoint Point, 1
   
        'Send a data point to the current command
        Point.X = StartPoint.X + 4
        Point.Y = StartPoint.Y + 4
        Point.Z = StartPoint.Z + 0
        CadInputQueue.SendDataPoint Point, 1
   
        'Send a data point to the current command
        Point.X = StartPoint.X + 0
        Point.Y = StartPoint.Y + 4
        Point.Z = StartPoint.Z + 0
        CadInputQueue.SendDataPoint Point, 1
   
        'Send a data point to the current command
        Point.X = StartPoint.X + 0
        Point.Y = StartPoint.Y + 0
        Point.Z = StartPoint.Z + 0
        CadInputQueue.SendDataPoint Point, 1
   
        CommandState.StartDefaultCommand
        
       CadInputQueue.SendCommand "PLACE SMARTLINE"
 
        'Coordinates are in master units
        StartPoint.X = myEndPt.X
        StartPoint.Y = myEndPt.Y
        StartPoint.Z = myEndPt.Z
 
        'Send a data point to the current command
        Point.X = StartPoint.X
        Point.Y = StartPoint.Y
        Point.Z = StartPoint.Z
        CadInputQueue.SendDataPoint Point, 1
 
        'Send a data point to the current command
        Point.X = StartPoint.X + 4
        Point.Y = StartPoint.Y + 0
        Point.Z = StartPoint.Z + 0
        CadInputQueue.SendDataPoint Point, 1
   
        'Send a data point to the current command
        Point.X = StartPoint.X + 4
        Point.Y = StartPoint.Y + 4
        Point.Z = StartPoint.Z + 0
        CadInputQueue.SendDataPoint Point, 1
   
        'Send a data point to the current command
        Point.X = StartPoint.X + 0
        Point.Y = StartPoint.Y + 4
        Point.Z = StartPoint.Z + 0
        CadInputQueue.SendDataPoint Point, 1
   
        'Send a data point to the current command
        Point.X = StartPoint.X + 0
        Point.Y = StartPoint.Y + 0
        Point.Z = StartPoint.Z + 0
        CadInputQueue.SendDataPoint Point, 1
   
        CommandState.StartDefaultCommand
        
        End If
Wend

End Sub

Parents
  • Is there any way to get a cell element to use the .AsLineElement callout

    No: a cell is not a line.  It may contain one or more lines, but .AsLineElement can't auto-magically work out which line.

    If myElement.IsCellElement Then

    After that statement, you need to analyse the cell and look for lines. Use myElement.AsCellElement.GetSubElements to get an enumeration of the cell's components.  Iterate that object to find your line(s)...

    Dim oComponents As ElementEnumerator
    Set oComponents = myElement.AsCellElement.GetSubElements ()
    '  Search oComponents for interesting elements

     
    Regards, Jon Summers
    LA Solutions

  • Thanks Jon, that makes perfect sense. It wouldn't know which line in the cell I want. I appreciate the direction!

  • So I think I have my code set up properly, it doesn't return any errors. I don't know if AECOsim handles sub-elements differently than straight Microstation or if it's my inexperience with VBA, but as it loops through, it does not return sub-elements. myEndPoints(0) and myEndPoints(1) hold value 0,0,0 through the loop, and after the initial cell is found, it doesn't appear to recognize any additional elements. All my gusset plates get places at 0,0,0 instead of on the ABD lines. I'll include my code one more time just in case something obvious sticks out. Thanks again for all your help!

    Option Explicit
    
    Function MyMatchSymbology(ByVal myLine As LineElement) As Boolean
        MyMatchSymbology = False
            If myLine.Level.Name = "S-PHYS-MEMB" Then
            MyMatchSymbology = True
            End If
    End Function
    
    Sub GussetPlates()
    
    'Scan For Horizontal Bracing
    Dim StartPoint As Point3d
    Dim Point As Point3d, Point2 As Point3d
    Dim myLine As LineElement
    
    Dim myCounter As Integer
    Dim myElementEnumerator As ElementEnumerator
    Dim myScanCriteria As New ElementScanCriteria
    Dim myElement As Element
    
    Dim myGussPL As Level
    Dim myHB As Level
    Dim myVB As Level
    Set myHB = ActiveDesignFile.Levels("S-STL-HB")
    Set myVB = ActiveDesignFile.Levels("S-STL-VB")
    Set myGussPL = ActiveDesignFile.Levels("S-STL-PLAT-GUSS")
    
    Dim myPoints As Point3d
    Dim myEndPt As Variant
    Dim myStartPt As Variant
    Dim myRange As Range3d
    
    myScanCriteria.ExcludeNonGraphical
    myScanCriteria.ExcludeAllLevels
    myScanCriteria.IncludeLevel myHB
    
    Set myElementEnumerator = ActiveModelReference.Scan(myScanCriteria)
    myElementEnumerator.Reset
    
    While myElementEnumerator.MoveNext
        Set myElement = myElementEnumerator.Current
            If myElement.IsCellElement Then
                Dim myComponents As ElementEnumerator
                Set myComponents = myElement.AsCellElement.GetSubElements()
                    Do While myComponents.MoveNext
                        If myComponents.Current.IsLineElement Then
                            If MyMatchSymbology(myComponents.Current.AsLineElement) Then
                                With myComponents.Current.AsLineElement
                                    Dim myEndPoints(0 To 1) As Point3d
                                    myEndPoints(0) = .StartPoint
                                    myEndPoints(1) = .EndPoint
                                End With
                            End If
                        End If
                    Loop
                    
                ActiveSettings.Level = myGussPL
            
                CadInputQueue.SendCommand "PLACE SMARTLINE"
     
            'Coordinates are in master units
                    
            StartPoint.X = myEndPoints(0).X
            StartPoint.Y = myEndPoints(0).Y
            StartPoint.Z = myEndPoints(0).Z
     
            'Send a data point to the current command
            Point.X = StartPoint.X
            Point.Y = StartPoint.Y
            Point.Z = StartPoint.Z
            CadInputQueue.SendDataPoint Point, 1
     
            'Send a data point to the current command
            Point.X = StartPoint.X + 4
            Point.Y = StartPoint.Y + 0
            Point.Z = StartPoint.Z + 0
            CadInputQueue.SendDataPoint Point, 1
       
            'Send a data point to the current command
            Point.X = StartPoint.X + 4
            Point.Y = StartPoint.Y + 4
            Point.Z = StartPoint.Z + 0
            CadInputQueue.SendDataPoint Point, 1
       
            'Send a data point to the current command
            Point.X = StartPoint.X + 0
            Point.Y = StartPoint.Y + 4
            Point.Z = StartPoint.Z + 0
            CadInputQueue.SendDataPoint Point, 1
       
            'Send a data point to the current command
            Point.X = StartPoint.X + 0
            Point.Y = StartPoint.Y + 0
            Point.Z = StartPoint.Z + 0
            CadInputQueue.SendDataPoint Point, 1
       
            CommandState.StartDefaultCommand
            
            CadInputQueue.SendCommand "PLACE SMARTLINE"
     
            'Coordinates are in master units
            
            StartPoint.X = myEndPoints(1).X
            StartPoint.Y = myEndPoints(1).Y
            StartPoint.Z = myEndPoints(1).Z
     
            'Send a data point to the current command
            Point.X = StartPoint.X
            Point.Y = StartPoint.Y
            Point.Z = StartPoint.Z
            CadInputQueue.SendDataPoint Point, 1
     
            'Send a data point to the current command
            Point.X = StartPoint.X + 4
            Point.Y = StartPoint.Y + 0
            Point.Z = StartPoint.Z + 0
            CadInputQueue.SendDataPoint Point, 1
       
            'Send a data point to the current command
            Point.X = StartPoint.X + 4
            Point.Y = StartPoint.Y + 4
            Point.Z = StartPoint.Z + 0
            CadInputQueue.SendDataPoint Point, 1
       
            'Send a data point to the current command
            Point.X = StartPoint.X + 0
            Point.Y = StartPoint.Y + 4
            Point.Z = StartPoint.Z + 0
            CadInputQueue.SendDataPoint Point, 1
       
            'Send a data point to the current command
            Point.X = StartPoint.X + 0
            Point.Y = StartPoint.Y + 0
            Point.Z = StartPoint.Z + 0
            CadInputQueue.SendDataPoint Point, 1
       
            'CommandState.StartDefaultCommand
            
            End If
    Wend
    
    End Sub

  • I think I see what's wrong... "myLine" in the fuction is not tied to anything. I will work on fixing it.

  • If that doesn't fix it, post a test .dgn file.  I don't know anything about AECOsim, but I have some time today and could have a go at it.

    Code... We're the good guys now.

  • I think I have my code set up properly, it doesn't return any errors

    Divide and conquer! Break your code into smaller procedures. Each procedure has a specific task. This organisation makes subsequent understanding and maintenance much simpler …

    Sub GussetPlates()
    
      'Scan For Horizontal Bracing
      Dim myLine                                As LineElement
    
      Dim myCounter                             As Integer
      Dim oElements                             As ElementEnumerator
      Dim myScanCriteria                        As New ElementScanCriteria
      Dim myElement                             As Element
    
      Dim myGussPL                              As Level
      Dim myHB                                  As Level
      Dim myVB                                  As Level
      Set myHB = ActiveDesignFile.Levels("S-STL-HB")
      Set myVB = ActiveDesignFile.Levels("S-STL-VB")
      Set myGussPL = ActiveDesignFile.Levels("S-STL-PLAT-GUSS")
    
      myScanCriteria.ExcludeNonGraphical
      myScanCriteria.ExcludeAllLevels
      myScanCriteria.IncludeLevel myHB
    
      Set oElements = ActiveModelReference.Scan(myScanCriteria)
      oElements.Reset
    
      While oElements.MoveNext
        Set myElement = oElements.Current
        If myElement.IsCellElement Then
          Dim myComponents As ElementEnumerator
          Set myComponents = myElement.AsCellElement.GetSubElements()
          Do While myComponents.MoveNext
            If myComponents.Current.IsLineElement Then
              If MyMatchSymbology(myComponents.Current.AsLineElement) Then
                Dim points (0 To 1)             As Point3d
                ProcessLineElement points myComponents.Current.AsLineElement
                CreateGusset points
              End If
            End If
          Loop
    
    
    
        End If
      Wend
    
    End Sub
    

    MyMatchSymbology can do whatever you want to test the element's symbology …

    Function MyMatchSymbology(ByVal myLine As LineElement) As Boolean
      MyMatchSymbology = False
      If myLine.Level.Name = "S-PHYS-MEMB" Then
        MyMatchSymbology = True
      End If
    End Function
    

    Do whatever you need to do with the component line …

    Sub ProcessLineElement (ByRef points() As Point3d, ByVal oLine As LineElement)
      points(0) = oLine.StartPoint
      points(1) = oLine.EndPoint
    End Sub
    

    Use extracted data to create something …

    Sub CreateGusset (ByRef points() As Point3d)
        ActiveSettings.Level = myGussPL
    
        CadInputQueue.SendCommand "PLACE SMARTLINE"
    
        'Coordinates are in master units
        Dim StartPoint                          As Point3d
        StartPoint.X = points(0).X
        StartPoint.Y = points(0).Y
        StartPoint.Z = points(0).Z
    
        'Send a data point to the current command
        Dim Point                               As Point3d
        Point.X = StartPoint.X
        Point.Y = StartPoint.Y
        Point.Z = StartPoint.Z
        CadInputQueue.SendDataPoint Point, 1
    
        'Send a data point to the current command
        Point.X = StartPoint.X + 4
        Point.Y = StartPoint.Y + 0
        Point.Z = StartPoint.Z + 0
        CadInputQueue.SendDataPoint Point, 1
    
        'Send a data point to the current command
        Point.X = StartPoint.X + 4
        Point.Y = StartPoint.Y + 4
        Point.Z = StartPoint.Z + 0
        CadInputQueue.SendDataPoint Point, 1
    
        'Send a data point to the current command
        Point.X = StartPoint.X + 0
        Point.Y = StartPoint.Y + 4
        Point.Z = StartPoint.Z + 0
        CadInputQueue.SendDataPoint Point, 1
    
        'Send a data point to the current command
        Point.X = StartPoint.X + 0
        Point.Y = StartPoint.Y + 0
        Point.Z = StartPoint.Z + 0
        CadInputQueue.SendDataPoint Point, 1
    
        CommandState.StartDefaultCommand
    
        CadInputQueue.SendCommand "PLACE SMARTLINE"
    
        'Coordinates are in master units
    
        StartPoint.X = points(1).X
        StartPoint.Y = points(1).Y
        StartPoint.Z = points(1).Z
    
        'Send a data point to the current command
        Point.X = StartPoint.X
        Point.Y = StartPoint.Y
        Point.Z = StartPoint.Z
        CadInputQueue.SendDataPoint Point, 1
    
        'Send a data point to the current command
        Point.X = StartPoint.X + 4
        Point.Y = StartPoint.Y + 0
        Point.Z = StartPoint.Z + 0
        CadInputQueue.SendDataPoint Point, 1
    
        'Send a data point to the current command
        Point.X = StartPoint.X + 4
        Point.Y = StartPoint.Y + 4
        Point.Z = StartPoint.Z + 0
        CadInputQueue.SendDataPoint Point, 1
    
        'Send a data point to the current command
        Point.X = StartPoint.X + 0
        Point.Y = StartPoint.Y + 4
        Point.Z = StartPoint.Z + 0
        CadInputQueue.SendDataPoint Point, 1
    
        'Send a data point to the current command
        Point.X = StartPoint.X + 0
        Point.Y = StartPoint.Y + 0
        Point.Z = StartPoint.Z + 0
        CadInputQueue.SendDataPoint Point, 1
    
        'CommandState.StartDefaultCommandEnd Sub
    

     
    Regards, Jon Summers
    LA Solutions

  • Thanks for the offer minion! I was out of the office the past few days and just saw your reply now. I discovered that part of my problem is I have a cell within a cell, and the line I'm looking for is in that nested cell. I'm going to try to push a little further, but I'm sure I'll be back. I'm just not finding a lot of resources on how AECOsim builds it's objects so it's been slow going. Thanks again!

  • Thanks again Jon, all your help in right on point. The problem I'm having is I didn't (maybe still don't haha) understand how AECOsim builds it's steel objects. It looks like the line I'm trying to query is part of a cell within a cell. So I think I have to say .GetSubElements() twice. The way my code is written now is returning the point within the cell and looping through the rest with no results because we call out .IsLineElement,  and the rest are cells.

       

  • Hi Amador,

    It looks like Jon simplified it a bit for you.  It should be much easier now.

    If you don't mind picking the lines one by one, you could make an ILocates module and try the CommandState.GetlocatedElement method.  I'm not sure it will work for your case though.

    Minion

    Code... We're the good guys now.

  • you had to set elemdata to include nestcell in the scancriteria in mdl  to traverse nested cells..
    think you might need to set something similar in mvba too or it just returns the elements in the cell and a cell header is just another element.

    i think in mvba you need to use MoveToNextElement Method for nested cells when you encounter a cell in a cell

    sorry been a long time since I programmed..  but scanning within cells to get info used to be quite common.
    PDS, Omnipipe, 3DM, etc used to store their UD/rotations on the first line/pointstring in a cell.
    AECOsim is following in their footsteps I expect.

  • TF : Triforma
    VIS :visible
    BL : Block cell
    The line at the end is probably the one you can see.

    So test the CELL name  is TFVISBL then go thru that CELL and set the start end to the start end of the line in the cell.
    I am guessing there is always just one line in the TFVISBL cell?

    Reticent of 3DM/Plantspace..  does the cell have a scaling?

Reply Children
No Data