addelementS method [VBA V8i SS3 fr ]

Bonjour,

I try to round off several lineelement

Dim Sc As ElementScanCriteria
Dim Ee As ElementEnumerator
Set Sc = New ElementScanCriteria
Sc.ExcludeAllTypes
Sc.IncludeType msdElementTypeLine
Set Ee = ActiveModelReference.Scan(Sc)
Dim LLanc As LineElement
Dim PtLL1 As Point3d
Dim PtLL2 As Point3d
Dim Ar() As Element
Do While Ee.MoveNext
    Dim LLNew As LineElement
    Set LLanc = Ee.Current
        With LLanc.startPoint
        PtLL1 = Point3dFromXYZ(Round(.X, 3), Round(.Y, 3), Round(.Z, 3))
        End With
        With LLanc.EndPoint
        PtLL2 = Point3dFromXYZ(Round(.X, 3), Round(.Y, 3), Round(.Z, 3))
        End With
    Set LLNew = CreateLineElement2(LLanc, PtLL1, PtLL2)
    ActiveModelReference.RemoveElement LLanc
    'ActiveModelReference.AddElement LLNew ' doesn't work if ee > 1024
Loop
RedrawAllViews

Doesn't work if the number of lines is up to 1024... 210

So I made a trick not very academic with « if..then.. end if » and « goto »

Suite:
If Ee.MoveNext Then
    Set LLanc = Ee.Current
    With LLanc.startPoint
    PtLL1 = Point3dFromXYZ(Round(.X, 3), Round(.Y, 3), Round(.Z, 3))
    End With
    With LLanc.EndPoint
    PtLL2 = Point3dFromXYZ(Round(.X, 3), Round(.Y, 3), Round(.Z, 3))
    End With
    Set LLNew = CreateLineElement2(LLanc, PtLL1, PtLL2)
    ActiveModelReference.RemoveElement LLanc
    ActiveModelReference.AddElement LLNew
    Ee.MoveNext
    GoTo Suite
End If
RedrawAllViews

I’d like tu use addelements method but i don’t see a example,

I ‘ve tried namedgroup, elementenumerator , arrays seems to be the best way but i failed

Does anyone have an example? Or help

Parents
  • Hi Laurent,

    with all respect, you approach (and consequently your code) is wrong from several reasons.

    As Jon explained, it's not good idea to create new elements in element enumerator. The scan enumerator caches only a few elements and when it's necessary, it reads a next part of DGN file. So when you create a new element (or you modify existing element in such way it has to be moved the end of the file; because of its size change), the enumerator will read also this newly created element, which is never correct.

    But what is more important: To create a new element and to remove the old one is completely wrong in my opinion. In fact you do not round line elements, but you create lines copies with rounded vertices. But the result elements are not the same, e.g. ElementIDs are different ... which can be a critical issue in some scenarios.

    This code (structured to single response subs and functions, which I prefer), should work:

    Option Explicit
    
    Public Sub RoundLineVerticesInActiveModel()
        
        Dim esc As ElementScanCriteria
        Set esc = CreateScanCriteria
       
        ProcessAllLinesInActiveModel esc, 3
    
    End Sub
    
    Private Function CreateScanCriteria() As ElementScanCriteria
    
        Dim esc As New ElementScanCriteria
        esc.ExcludeAllTypes
        esc.IncludeType msdElementTypeLine
        
        Set CreateScanCriteria = esc
    
    End Function
    
    Private Sub ProcessAllLinesInActiveModel(esc As ElementScanCriteria, precision As Integer)
    
        Dim ee As ElementEnumerator
        Set ee = ActiveModelReference.Scan(esc)
        
        Do While ee.MoveNext
            RoundLineVertices ee.Current.AsLineElement, precision
            ee.Current.Rewrite
        Loop
    
    End Sub
    
    Private Function RoundLineVertices(line As LineElement, precision As Integer) As LineElement
    
        Dim startRounded As Point3d
        startRounded = Round3dCoordinate(line.StartPoint, precision)
        line.ModifyVertex 0, startRounded
        
        Dim endRounded As Point3d
        endRounded = Round3dCoordinate(line.EndPoint, precision)
        line.ModifyVertex 1, endRounded
    
    End Function
    
    Private Function Round3dCoordinate(coordinate As Point3d, precision As Integer)
    
        Dim rx As Double
        rx = Round(coordinate.X, precision)
        
        Dim ry As Double
        ry = Round(coordinate.Y, precision)
        
        Dim rz As Double
        rz = Round(coordinate.Z, precision)
        
        Round3dCoordinate = Point3dFromXYZ(rx, ry, rz)
    
    End Function

    With regards,

      Jan

    Answer Verified By: LaurentD 

Reply
  • Hi Laurent,

    with all respect, you approach (and consequently your code) is wrong from several reasons.

    As Jon explained, it's not good idea to create new elements in element enumerator. The scan enumerator caches only a few elements and when it's necessary, it reads a next part of DGN file. So when you create a new element (or you modify existing element in such way it has to be moved the end of the file; because of its size change), the enumerator will read also this newly created element, which is never correct.

    But what is more important: To create a new element and to remove the old one is completely wrong in my opinion. In fact you do not round line elements, but you create lines copies with rounded vertices. But the result elements are not the same, e.g. ElementIDs are different ... which can be a critical issue in some scenarios.

    This code (structured to single response subs and functions, which I prefer), should work:

    Option Explicit
    
    Public Sub RoundLineVerticesInActiveModel()
        
        Dim esc As ElementScanCriteria
        Set esc = CreateScanCriteria
       
        ProcessAllLinesInActiveModel esc, 3
    
    End Sub
    
    Private Function CreateScanCriteria() As ElementScanCriteria
    
        Dim esc As New ElementScanCriteria
        esc.ExcludeAllTypes
        esc.IncludeType msdElementTypeLine
        
        Set CreateScanCriteria = esc
    
    End Function
    
    Private Sub ProcessAllLinesInActiveModel(esc As ElementScanCriteria, precision As Integer)
    
        Dim ee As ElementEnumerator
        Set ee = ActiveModelReference.Scan(esc)
        
        Do While ee.MoveNext
            RoundLineVertices ee.Current.AsLineElement, precision
            ee.Current.Rewrite
        Loop
    
    End Sub
    
    Private Function RoundLineVertices(line As LineElement, precision As Integer) As LineElement
    
        Dim startRounded As Point3d
        startRounded = Round3dCoordinate(line.StartPoint, precision)
        line.ModifyVertex 0, startRounded
        
        Dim endRounded As Point3d
        endRounded = Round3dCoordinate(line.EndPoint, precision)
        line.ModifyVertex 1, endRounded
    
    End Function
    
    Private Function Round3dCoordinate(coordinate As Point3d, precision As Integer)
    
        Dim rx As Double
        rx = Round(coordinate.X, precision)
        
        Dim ry As Double
        ry = Round(coordinate.Y, precision)
        
        Dim rz As Double
        rz = Round(coordinate.Z, precision)
        
        Round3dCoordinate = Point3dFromXYZ(rx, ry, rz)
    
    End Function

    With regards,

      Jan

    Answer Verified By: LaurentD 

Children
  • Hi Laurent,

    i thought scancriteria only ran once

    this is very widespread mistake. In fact, your formulation makes no sense, because Scan Criteria does not run anything ;-)

    To be precise (because we are in developers' community):

    • Element Scan Criteria defines search criteria (filter) that will be applied to scan process. It's object that holds a definition of the filter.
    • Scan() method does not scan anything (so naming is misleading a bit), it "only" creates ElementEnumerator object with ElementScanCriteria filter applied.
    • ElementnEnumerator is a tool that can be used to iterate model (active or reference). So when talking about scanning model, the enumerator is the tool that do it.

    Main features of enumerator (it's common to many programming languages) are:

    • You can go by one step forward only.
    • There is no index.
    • It will stop at the end of a list / collection (model in the discussed case).

    So the definition is not "it will run once only", but "it will stop at the end of the model". But "end of the model" is not fixed, so when you add elements during scanning or modify existing element and change its size, so it has to be rewritten to the end of the file, the end is moving.

    With regards,

      Jan