Coordinate modification z of a complex shape

I resume this old discussion of 2016 and I ask .... in the event that we find a complex form (MSDelementtyPecomplexshape) how the function should be changed to be able to elevate a shape that contains two arches and two lines.

Option Explicit

Sub TestMoveShape()

    Dim elemId As DLong
    elemId = DLongFromLong(1307192)
    
    Dim el As Element
    Set el = ActiveModelReference.GetElementByID(elemId)
    
    If (msdElementTypeShape = el.Type) Then
        processShape el.AsShapeElement
    End If
    
End Sub

Private Sub processShape(shape As ShapeElement)

    Dim numOfVertices As Long
    numOfVertices = shape.VerticesCount
    
    Dim index As Long
    
    For index = 1 To numOfVertices
        shape.vertex(index) = moveVertex(shape.vertex(index))
    Next
    
    shape.Rewrite

End Sub

Private Function moveVertex(vertex As Point3d) As Point3d

    Const zVal = 53.65
    
    moveVertex = vertex
    moveVertex.Z = zVal

End Function

Parents Reply Children
  • Thanks, Jon. That confirms to me that I was on the right path, but got lost in the woods.

    The general syntax of that method is :
    trns = Transform3dFromMatrix3dAndFixedPoint3d(matrix, origin), where origin is the pivot (3D point). The problem is with the "matrix" component, which is a placeholder for a transformational matrix (or a Matrix3d type), if I understand correctly.

    But when I am referring to the Microstation VBA help, looking up "Matrix3d Type" returns a wall of text, with a bunch of matrix subtypes. And I am completely lost there.
    Could you please tell me which one is the best one to be used for translation operations ? I am guessing one of two  :
    - Matrix3dFromVectorAndRotationAngle (however, I've tried changing the Z vector values and didn't work)
    - Matrix3dFromMatrix3dTimesMatrix3d, which returns the product of two matrices.


    Regards,

    Paul

  • The problem is with the "matrix" component

    If you're not interested in rotation, then supply the identity matrix Matrix3dIdentity.

     
    Regards, Jon Summers
    LA Solutions

  • I've tried using an example of IdentityMatrix I've found on your site (slightly adapted), but it does not work. No errors, just not doing anything. What am I doing wrong, please ?

        Dim m1 As Matrix3d
        Dim m2 As Matrix3d
        Dim multiplication As Matrix3d
        
        ZAxis = 10   'this is the elevation value the element needs to be translated to
        origin = Point3dFromXYZ(0, 0, ZAxis)
        m1 = Matrix3dFromAxisAndRotationAngle(ZAxis, 0) 'no rotation angle, just translation
        m2 = Matrix3dIdentity
        
        multiplication = Matrix3dFromMatrix3dTimesMatrix3d(m1, m2)
        trns = Application.Transform3dFromMatrix3dAndFixedPoint3d(multiplication, origin)

  • Hi Paul,

    at first, please use Insert > Insert Code tool, when you want to share any code snippet (even one line only). It ensures it's displayed better.

    Matrix3dFromAxisAndRotationAngle(ZAxis, 0) 'no rotation angle, just translation

    What looks like a bug to me is that you use variable named ZAxis, but it's used to define rotation around X (0), not about Z (value should be 2).

    Also, it's not clear where ZAxis comes from and what is its value.

    Regards,

      Jan

  • Hey Jan,

    Thank you for your quick reply. I do apologize for not formatting the code properly - will keep that in mind.

    You are probably right, I might have used the wrong 3dMatrix component. I am just looking for something that would do a translation along the Z axis (no rotation or scaling) and I was trying different things, in hope that something will work. I know I should multiply the Matrix3dIdentity by a translation matrix, but I am not sure what is the exact matrix that does that.

    Best regards,
    Paul

  • m1 = Matrix3dFromAxisAndRotationAngle(ZAxis, 0) 'no rotation angle, just translation

    You're failing to understand the mechanics of matrices.  A Matrix3d can convey rotation, scaling or skew but not translation.

    I am just looking for something that would do a translation

    You need a Transform3d to perform translation.

    I should multiply the Matrix3dIdentity by a translation matrix

    Why do you think that?  You need a transformation matrix.  If you want only to translate then rotation and scaling don't enter the equation, and no rotation matrix is required.  Where the Transform3d API requires a rotation matrix, use the no-op Matrix3dIdentity.  In some cases, the identity matrix is supplied invisibly...

    Transform3d = Transform3dFromPoint3d (translation) ' Returns a transformation with identity matrix part 

    That's the same as writing this...

    Transform3d = Transform3dFromMatrix3dPoint3d (Matrix3dIdentity, translation)

     
    Regards, Jon Summers
    LA Solutions

  • Jon, thank you for your patience.
    By using the method you suggested I've managed to get the code working, but it's doing the same thing as the previous method (see below), which is adding the specified value (10 in this case) to the current elevation of the element. What I am trying to achieve is translate the element to that specific elevation, not add up to the existing one. Does it make sense ?

     ele.Transform Transform3dFromMatrix3dPoint3d(Matrix3dFromScaleFactors(1, 1, 1), Point3dFromXYZ(0, 0, 10))


    So I am guessing what I need to do is to deconstruct the complex element, figure out the lowest elevation point and then translate the element by using a subtraction operation, either on the positive Z or negative Z.

  • Hey Jon, sorry for bringing this up again. Following you and Jan's advices, I've got this script working perfectly for any 2D elements. However, I was curious how could I make it work for 3D elements (such as meshes, smart solids or surfaces). Obviously, when running the script with a 3D element selected, it will throw an error ("Element has not beed added to a model"), when executing the Rewrite bit.  Any ideas, please ?

        Dim ele As Element
        Dim myArray() As Element
        Dim oPH As PropertyHandler
        Dim trns As Transform3d
        Dim translation As Point3d
        
        myArray = ActiveModelReference.GetSelectedElements.BuildArrayFromContents
        Set ele = myArray(0)
            
        Set oPH = CreatePropertyHandler(ele)
        oPH.SelectByAccessString ("RangeLow")
        cpoint = oPH.GetValueAsPoint3d
        Debug.Print "This element's low point is: " & cpoint.Z
        
        newElev = 103
        ZAxis = newElev - cpoint.Z
        translation = Point3dFromXYZ(0, 0, ZAxis)
        'trns = Transform3dFromPoint3d(translation)                                             'method 1
        'trns = Transform3dFromMatrix3dPoint3d(Matrix3dFromScaleFactors(1, 1, 1), translation)  'method 2
        'trns = Transform3dFromMatrix3dPoint3d(Matrix3dIdentity, translation)                   'method 3
        trns = Transform3dFromPoint3d(translation)                                              'method 4
        
        ele.Transform trns
        ele.Rewrite



  • Hi Paul,

    I was curious how could I make it work for 3D elements

    I recommend to ask in a new post, because this whole thread started with another question from somebody else several months ago.

    Obviously, when running the script with a 3D element selected, it will throw an error ("Element has not beed added to a model"), when executing the Rewrite bit.  Any ideas, please ?

    Did you check what element is the first in array? What type? Has it element id?

    Without knowing source data, it's hard to guess.

    Regards,

      Jan