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 = 0Private 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 HandleErrorDim strRfName As StringDim RefInfoP As LongDim iCnt As IntegerDim dblUORsToMUs As Double
GetClippointsAtt = FalsedblUORsToMUs = oAtt.UORsPerMasterUnitRefInfoP = mdlRefFile_getInfo(oAtt.MdlModelRefP)If RefInfoP = NULLPtr Then Exit FunctionstrRfName = "((struct referenceFile *)" & RefInfoP & ")"intNumvertices = GetCExpressionValue(strRfName & "->clip.clip_vertices") & " "ReDim aPntRefClip(0 To intNumvertices)
Dim str As Stringstr = ""MsgBox intNumverticesFor 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).YNext iCntGetClippointsAtt = TrueExit 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
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 StringDim RefInfoP As LongDim oAtt as Attachment
RefInfoP = mdlRefFile_getInfo(oAtt.MdlModelRefP)If RefInfoP = NULLPtr Then Exit Function
strRfName = "((struct referenceFile *)" & RefInfoP & ")"
Dim clipElementID As DLongclipElementID = 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++.