[Microstation V8i] MDL Mesh Functions in VBA

Hi All,

Can anyone give me an example of how to use the MDL mesh function mdlMesh_getPolyfaceArraysDirect.

I'm struggling to understand how to pass the int and point3d arrays into the VBA decleration as Longs.

Declare Function mdlMesh_getPolyfaceArraysDirect Lib "stdbspline.dll" ( ByVal pMeshHeaderED As Long , ByVal pIndices As Long , ByVal pXYZ As Long , ByRef pNumIndexPerFace As Long , ByRef pNumFace As Long ) As Long

Return Value

Type Description
StatusInt SUCCESS if the desired output is successfully returned

Parameters

Type Name Mode Description
MSElementDescr const* pMeshHeaderED IN top of descriptor tree containing the mesh.
EmbeddedIntArray* pIndices OUT polyface index array.
EmbeddedDPoint3dArray* pXYZ OUT vertex coordinate array (3D points).
int* pNumIndexPerFace OUT max number of indices/vertices per face (= 1 if variable-size face loops)
int* pNumFace OUT number of faces (#entries in index array if variable-size face loops).

    Dim success As Long
    Dim element As element
    Dim indicies() As Long
    Dim verticies() As Point3d
    Dim numOfIndicies As Long
    Dim numOfFaces As Long
    
    success = mdlMesh_getPolyfaceArraysDirect(element.MdlElementDescrP(False), indicies, verticies, numOfIndicies, numOfFaces)

Kind Regards,

Mike

Parents
  • I'm struggling to understand how to pass the int and point3d arrays into the VBA decleration as Longs

    First, add the VBA function declaration to your VBA module.  This is copied from the MDL function reference manual...

    VBA Wrapper Declaration

    Declare Function mdlMesh_getPolyfaceArraysDirect Lib "stdbspline.dll" ( _
            ByVal pMeshHeaderED As Long , _
            ByVal pIndices As Long , _
            ByVal pXYZ As Long , _
            ByRef pNumIndexPerFace As Long , _
            ByRef pNumFace As Long ) As Long
    

    Undocumented Helpers for Pointers in VBA

    Because VBA doesn't do pointers, the VBA declaration writes MDL pointers as VBA Long.

    VBA arrays are SafeArrays.  Their structure is quite unlike the C-style arrays used in MDL.  The first three parameters in that function declaration, passed ByVal, are pointers to arrays.

    Microsoft provide some undocumented helpers for exactly your sort of task: look them up here.

     
    Regards, Jon Summers
    LA Solutions

    Answer Verified By: Michael Laws 

  • Thanks Jon, this is exactly what I'm looking for. As always, very helpfull! 

  • Hi Micheal,

    I have the same problem, but unfortunately I'm not getting anywhere with the tip from Jon.

    Could you please show me how you got the content of the array's pIndices and pXYZ?

    with best greetings

    Tobias

  • Hi Tobias,

    Could you please show me how you got the content of the array's pIndices and pXYZ?

    there can be a problem that this (2 years old) discussion is about MicroStation V8i (SELECTseries 4), whereas your question (not bad idea to provide proper link) is about MicroStation CONNECT Edition.

    How native functions are called changed a bit, both because of migration from 32bit to 64bit, and also from VBA 6 to VBA 7. As described in "Changes for VBA 7.1" chapter (did you check this text in MicroStation VBA help?), different data types have to be used (e.g. where pointer was passed as long, now it has to be PtrSafe).

    With regards,

      Jan

  • Hi Jan,

    yes, I have read the chapter.
    I have about 10 mdl functions that I migrated from v8i to connect (insert ptrsave and change type fom long to longptr).

    But I have never had a mdl function with an array as output. 

    So I wanted to ask Micheal for his (v8i) solution and migrate it (hopefully) to connect.

    here I'm stuck:

    Declare PtrSafe Function mdlMesh_getPolyfaceArraysDirect Lib "stdbspline.dll" ( _
            ByVal pMeshHeaderED As LongPtr, _
            ByVal pIndices As LongPtr, _
            ByVal pXYZ As LongPtr, _
            ByRef pNumIndexPerFace As Long, _
            ByRef pNumFace As Long) As Long

    Function Mesh_auslesen(o_Mesh As Element) As Point3d()
    Dim o_pIndices As LongPtr
    Dim o_pXYZ As LongPtr
    Dim o_pNumIndexPerFace As Long
    Dim o_pNumFace As Long
    
    
    If 0 = mdlMesh_getPolyfaceArraysDirect (o_Mesh.MdlElementDescrP(False), o_pIndices, o_pXYZ, o_pNumIndexPerFace, o_pNumFace) Then
    
    ...
    
    End If
    
    
    End Function

    For o_pNumIndexPerFace and o_pNumFace I get matching values. But no matter how I use varptr, strptr. (e.g:

    Function Mesh_auslesen(o_Mesh As Element) As Point3d()
    Dim o_pIndices As LongPtr
    Dim o_pXYZ As Point3d 'no array possible
    Dim o_pNumIndexPerFace As Long
    Dim o_pNumFace As Long
    
    
    If 0 = mdlMesh_getPolyfaceArraysDirect(o_Mesh.MdlElementDescrP(False), o_pIndices, VarPtr(o_pXYZ), o_pNumIndexPerFace, o_pNumFace) Then
    
    End If
    
    
    End Function
    )

    I get only nonsense for  o_pXYZ (and o_pIndices).

    Can you help me to use the functions here correctly?

  • So I wanted to ask Micheal for his (v8i) solution and migrate it (hopefully) to connect.

    I do not want to be too pessimistic, but I think it's not straightforward, because V8i function returns EmbeddedIntArray and EmbeddedDPoint3dArray (which are originally JMDL structures), whereas CE function returns bvector (which is Bentley implementation of std:vector).

    So I think it makes sense to continue in this discussion in your original thread (because it's about CE).

    But I have never had a mdl function with an array as output. 

    It's not array, the function returns vector. I do not know whether C++ vector class can be accessed as array or not.

    With regards,

      Jan

Reply Children
  • I do not know whether C++ vector class can be accessed as array

    The C++ standard requires std::vector to organise its contents as a contiguous chunk of memory, just like an array.  In C++ we can get at the data of a std::vector as if it were an array...

    std::vector<something> vSomething;
    something pointerToArray* = &vSomething[0];

    However, I can't see a way to translate that to VBA.

    Can you help me to use the functions here correctly [with MicroStation CONNECT]?

    I don't think it's possible.  In general, VBA and C++ don't mix.  It's possibly only when C++ defines a function using a C-style syntax and when its parameters are C-style primitive variables or data-only structures.

    For example, MDL is an implementation of C and VBA can call its functions.  Likewise with the Microsoft Win32 API.  But technology has moved on!  VBA is a 20th century technology and we're now about to enter the third decade of the 21st century.

    Probably a right time to start to think about a migration

    I agree!

     
    Regards, Jon Summers
    LA Solutions

  • The C++ standard requires std::vector to organise its contents as a contiguous chunk of memory, just like an array.  In C++ we can get at the data of a std::vector as if it were an array...

    Well, I think I really do not need to explain what std::vector is and how it works ;-)

    But it's true my notice was not precise enough as I at that moment thought it's clear from its content: How std::vector (as memory structure identified by its pointer) can be accessed from VBA.

    Regards,

      Jan