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
  • Hi Tiziano,

    how the function should be changed to be able to elevate a shape that contains two arches and two lines.

    in my opinion you choose wrong approach:

    I do not know a context of original discussion and code, but as Jon wrote, it is wrong to move vertices individually, when an element offers Transform method.

    Also, another wrong assumption is that code used for simple shape can be easily transformed to be used with complex shape. Sometimes yes, but often not. The shape is simple element, whereas ComplexShape is complex element, consisting from more different elements internally. It means to access the content works in a different way.

    And it is situation where Transform method makes sense, because it allows to manipulate with the whole element in a uniform way, regardless its type.

    Or you are interested in some internal modifications, so not to simple move the whole element in Z axis direction?

    With regards,

      Jan

  • This weekend I work for us if I am able. From what I seemed to understand with "transform3d" I can make changes in the position and size of the various objects that are part of a selection group.
    Thank you
  • Transform3dFromMatrix3dPoint3d(...)
    However, instead of translating it to the specified elevation (10, in this case), it will simply add 10 to the existing elevation

    From VBA help: Returns a transformation from given matrix and translation parts.  So, yes, in your example it does what is expected.

    There are a lot of methods that work with Transform3d: search for Transform3d Type in VBA help.  Perhaps Transform3dFromMatrix3dAndFixedPoint3d will do what you want?

     
    Regards, Jon Summers
    LA Solutions

  • 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

Reply Children