How to obtain the clipping boundary of a reference?

This is the inverse of the problem I had last week.  I can successfully set a reference file's clipping boundary using VBA (by utilizing the code provided in the thread I previously posted in.)  That code uses the MDL function mdlRefFile_setClip()

As there does not seem to be a sister function that gets the clipping boundary, I did some research and found some code written by Harry Stegeman that fills a referenceFile structure by calling the MDL function mdlRefFile_getInfo().   Among the members of referenceFile is an array of clipping vertices.  I found Harry's code (one function among many) at this link

So, my goal is to fill an array of vertices with the clipping boundary of a given reference file.  I've modified Harry's code to accomplish this (see below.)  If i use a fence to clip the reference, I get back incomplete information from my VBA function - I don't get absolute coordinates, only relative coordinates from the center of  the clipped region.  For example, if the width of the fence is 2X and the depth is 2Y, the vertices returned are (-X, Y),  (X, Y), (X, -Y), (-X, -Y).  If I could figure out where the center of the fence is relative to the origin of the reference, I could probably make this work.

However, in the more general case of using an element to clip the reference  boundary, I am unable to obtain the vertices at all.  The code runs without error, but I get a vertex count of 0, and no vertices are returned.

Am I taking the wrong approach to this?  Any advice on what I'm doing wrong?

Thanks for any feedback,

Darel

 

'---------------------------------------------------------------------------------------
' Module    : modAttInfo
' DateTime  : 4-4-2004
' Author    : Harry Stegeman
' Purpose   : Get attachment info commands
'---------------------------------------------------------------------------------------
'
Option Explicit

Private Const m_strModuleName As String = "modAttInfo"
Private Const NULLPtr As Long = 0
Private Const conSpace = " "

Private Declare Function mdlRefFile_getInfo Lib "stdmdlbltin.dll" _
                                            (ByVal modelref As Long) As Long

Public Sub Main()

    On Error GoTo err_Main
    Dim oAttachment As Attachment
    Dim strLOGICAL_NAME As String
    strLOGICAL_NAME = "BORDER"  ' This is the logical name of the clipped reference.
    Set oAttachment = ActiveModelReference.Attachments.FindByLogicalName(strLOGICAL_NAME)
   
    Dim intNumvertices As Integer
    Dim aPntClip(20) As Point3d
    Dim result As Boolean
    result = GetClippointsAtt(oAttachment, intNumvertices, aPntClip())
   
    Exit Sub
   
err_Main:
    MsgBox "Error: Main"
End Sub


Public Function GetClippointsAtt(ByVal oAtt As Attachment, _
                                 ByRef intNumvertices As Integer, _
                                 ByRef aPntClip() As Point3d) As Boolean
'---------------------------------------------------------------------------------------
' Procedure : GetClippointsAtt
' DateTime  : 15-3-2004
' Author    : Harry Stegeman
' Purpose   : get clipping points attachment
'             returns true if success
'---------------------------------------------------------------------------------------
'
'Parameters:
'===========
'oAtt = attachment (input)
'intnumvertices = number of vertices (output)
'aPntClip() = array of clipping points attachment (output)

On Error GoTo HandleError
Dim strRfName As String
Dim RefInfoP As Long
Dim iCnt As Integer
Dim dblUORsToMUs As Double

GetClippointsAtt = False
dblUORsToMUs = oAtt.UORsPerMasterUnit
RefInfoP = mdlRefFile_getInfo(oAtt.MdlModelRefP)
If RefInfoP = NULLPtr Then Exit Function
strRfName = "((struct referenceFile *)" & RefInfoP & ")"
intNumvertices = GetCExpressionValue(strRfName & "->clip.clip_vertices") & " "
ReDim aPntRefClip(0 To intNumvertices)

Dim str As String
str = ""
MsgBox intNumvertices
For iCnt = 0 To intNumvertices - 1
    aPntClip(iCnt).X = GetCExpressionValue(strRfName & "->clip.clipP[" + CStr(iCnt) + "].x")
    aPntClip(iCnt).Y = GetCExpressionValue(strRfName & "->clip.clipP[" + CStr(iCnt) + "].y")
    aPntClip(iCnt) = Point3dScale(aPntClip(iCnt), 1 / dblUORsToMUs)
    MsgBox aPntClip(iCnt).X & " " & aPntClip(iCnt).Y
Next iCnt
GetClippointsAtt = True
Exit Function

HandleError:
MsgBox ("error: " & Err)
'Call modError.LogError(Err, Erl, Err.Source, m_strModuleName, "GetClippointsAtt")
End Function

  • The MDL ReferenceFile structure contains a number of nested structs including Clip_desc clip. If you look at the definition of Clip_desc (in MDL header file refernce.h) you will see, among other things, the following:

    
    typedef struct clip_desc
    {
      ElementId       clipElement;     /* Clipping element */
       …
      int             clip_vertices;   /* clipping vertices */
      DPoint2d       *clipP;           /* pointer to clipping points */
       …
    } Clip_desc;

    When the clip vertices are specified, then clipP points to an array of clip points; clip_vertices tells you how large the array is.

    But note also clipElement. If there are no clip points, but clipElement is non-zero, then you have the ElementID of the shape element from which the boundary is defined.

    Regards, Jon Summers
    LA Solutions

     
    Regards, Jon Summers
    LA Solutions

  • Jon,

    Thanks for the reply.

    I have one more issue, however.  ElementId is an unsigned 64-bit integer, and there seems to be no comparable type in VBA.  Is it possible to assign the value of  clipElement as a Long VBA variable?

    I'm trying the code that follows, and only getting errors.  I see in the help that I can declare a DLong type, and use functions like DLongFromInt64(), but I don't see any comparable conversion functions for Unsigned integer types.

    Dim strRfName As String
    Dim RefInfoP As Long
    Dim oAtt as Attachment


    RefInfoP = mdlRefFile_getInfo(oAtt.MdlModelRefP)
    If RefInfoP = NULLPtr Then Exit Function

    strRfName = "((struct referenceFile *)" & RefInfoP & ")"

    Dim clipElementID As DLong
    clipElementID = GetCExpressionValue(strRfName & "->clip.clipElement")

  • VB/VBA don't have unsigned integer — only Integer and Long, which are both signed. Nor do they have 64-bit integers of any kind, which is why Bentley use the DLong UDT to store a 64-bit ElementID in two 32-bit components.

    Unfortunately, you've run into a fundamental limitation of VB/VBA, which predate 64-bit computing by many moons. So last-century, I know.

    Frankly, the kind of this you are doing is not well-matched with VBA. When you start calling MDL functions, manipulating pointers, and using 64-bit numbers, you're venturing outside the safe boundaries of VB. It's time to consider moving to MDL or C++.

    Regards, Jon Summers
    LA Solutions

     
    Regards, Jon Summers
    LA Solutions