hexagon logo

Problem accessing CadModel.CADProjectPoint from Basic Script

Trying to access the my Cad model in the Graphics Display Window using a PC-DMIS basic script. Getting a "Missing parameter(s)" error message. Here's what I have with the error being generated on the last line seen below;

'==================
Sub GetProjectPointData()
'==================
Dim App As Object
Dim Part As Object
Dim Cmds As Object
Dim GWindow As Object
Dim CadWin As Object
Set App = CreateObject("PCDLRN.Application")
Set Part = App.ActivePartProgram
Set Cmds = Part.Commands
Set GWindow = Part.CadWindows
Set CadWin = GWindow.Item(1)
Dim CADMod As CadModel
Set CADMod = Part.CadModel
'
'
Dim RetVal As Boolean
Dim XT, YT, ZT, DIRX, DIRY, DIRZ, PX, PY, PZ, PDIRX, PDIRY, PDIRZ As Double
Dim FeatureName, FID As String
'
CadWin.Visible = True

XT=NetData(7,1)
YT=NetData(7,2)
ZT=NetData(7,3)
CADMod.CADProjectPoint(XT, YT, ZT,7,0,0, PX, PY, PZ, PDIRX, PDIRY, PDIRZ,2)



The Function info in the help menus has 13 parameters, (as do I). Haven't tried accessing the Graphics display window from a script before and not sure if i have everything right here, but it does compile without errors, so...

If anyone that has basic script/Pcdmis knowledge about this topic, it would be much appreciated if you could take a peek at this and steer me in the right direction if there are blaring issues seen at first glance. Alien


  • I've never tried that function, but note that it is a function and you are calling it as a subroutine. I would start by adding a "Result =" at the beginning of the line and declare Result as a suitable type (32 bit unsigned integer?).

    Looking at the function definition in the type library, it agrees on the 13 arguments,

        function CADProjectPoint(pointX: Double; pointY: Double; pointZ: Double;
                                 geometryFilterFlags: ENUM_CAD_GEOMETRY_FILTER_FLAGS;
                                 vectorOption: ENUM_CAD_VECTOR_OPTION;
                                 surfaceBoundaryOption: ENUM_CAD_SURFACE_BOUNDARY_OPTION;
                                 out pProjectPointX: Double; out pProjectPointY: Double;
                                 out pProjectPointZ: Double; out pProjectVectorI: Double;
                                 out pProjectVectorJ: Double; out pProjectVectorK: Double;
                                 out pCadHandle: ICadHandle): ENUM_CAD_RESULT; dispid 7;
    


    but your last one - 2 - is almost certainly wrong, as it is an OUT parameter - it must be a variable!
  • Response #2: NetData is a String Array I have set up as a global variable at the top of my program. The code in my example is just the code from a sub routine I created to call to from sub Main.

    Response #2: Agreed. Added this, and received a "Type Mismatch" error.

    Dim Result, CH As Integer
    Result = CADMod.CADProjectPoint(XT, YT, ZT,7,0,0, PX, PY, PZ, PDIRX, PDIRY, PDIRZ, CH)


    This function should be returning values for all of these variables: " PX, PY, PZ, PDIRX, PDIRY, PDIRZ, CH " in the call to CADProjectPoint. Passing in my XT, YT, ZT coordinates to have them projected onto model in Graphics display window, with returns representing model point values and vector relative to cad model.

    Thank for helping, but still compiles and producing error above during runtime. Is it that I need to define a "point" variable of sorts that would hold all the return values? Hmm.

  • Could it be you need variables for … 7, 0, 0, … too?
  • Responce #5:
    AndersI, first off, thanks for all you do for everyone on the boards here. I see your posts throughout issues I look up all the time and appreciate your contributions!

    Just did a test to check and see if "value" works versus enumeration "member" in a field that holds this type of information. Code below works both ways. First line under loop is commented out (which I've been using in my script). The second line where "DmisCmd.Feature = 4" is the enumeration value for F_LINE in the commented line.

    For Each DmisCmd In Cmds
    '        If DmisCmd.isFeature And DmisCmd.Feature = F_LINE  Then
            If DmisCmd.isFeature And DmisCmd.Feature = 4 Then
    .
    .
    .
    


    History of why I want to write this script:
    The script I'm writing to try and access the Graphics Display Window where my cad model resides pertains to me wanting to "OverRide Nominals" of points I measured using our Laser Tracker. After measuring net pads (we take 5 hits (vector_points) on each pad) on our tooling here at Fiat-Chrysler Automobiles, we have to go back and bump each point measured against the cad mode in the Graphics Display Window to aquire the proper nominal value for each point.

    Having anywhere from 6 to 30 net pads on any given piece of tooling out on the body shop floor, this means right-clicking on each vector point in the Edit Window (Summary Mode) and then selecting "Feature/OverRide Nominals", then clicking on the appropriate surface in the Graphics Display Window, check the surface highlighted surface in the "OverRide Nominals" window, and then click on the "Drop Point" values and click the OverRide Button. Not too hard to do, but time consuming.

    Script Benefits:
    The benefit for having a script that accesses the cad model in the Graphics Display Window could be used for all Tracker users and possibly even those that use PC-DMIS Scanning software. I've seen a lot of post on the boards pertaining to users trying to acquire nominal from Graphics Display Window after producing measured scans. I myself do not use PC-DMIS Scanning software and may never in the future, but never say never, ha.

    Current Script Conditions:
    Prior to looking into the CadModel.CADProjectPoint object, I was poking around trying to find a way to reproduce the override nominal values seen in the OverRide Nominals Window. What I came up with was this;

    *Read in the nominal and measured data from 2 net pad measurements (5 points on each net pad) and load it into the NetData(1 To 400,1 To 11) array. (Sub routine GetNetData).
    Col 1-3 will eventually represent the nominal value of the measured hit projected onto the cad model (x, y, and z, OverRide Nominal values).
    Col 4-6 represents the measured x, y, and z values of each hit on the net pad
    Col 7-9 represents the measured i,j, and k values of each hit on the net pad. (relative to tracker alignment at time of tool shoot).
    Col 10 represents the feature ID of each measured hit. (Hit name must have the word "NET" in it).
    Col 11 not used.

    *Load a LINE feature with the xyz measured values and ijk measured values from a net pad hit into "both" the Theoretical and Actuals xyz and ijk fields of the line. (Sub routine LoadLine). More about this line feature later!

    *Next, I construct a drop_point from the net pad hit (REF1) and the loaded LINE (REF2). (Sub routine CreateDrop). I write these drop_point theoretical values back out into spots 1-3 of the NetData array.

    This construction produces a point that has nominals very close to what is seen in the OverRide Nominals Window. They are slightly different because the ijk vector values of the measured hit (and subsequently the loaded line) are picked up and created from the tracker alignment which is not the same as the Cad Model alignment which is theoretically perfect and in car body position.

    Not wanting to be sloppy, (and always striving for perfection (OCD)), I kept searching for other possibilities to achieve perfect data. Below is the script and subroutines;

  • Attribute VB_Name = "OverRideNominals"
    '-----------------------
    'Global VARIABLE Declarations
    '-----------------------
    Dim NetData(1 To 400,1 To 11) As String
    Dim I As Long
    Dim CurrentNetFeature, TotalNetFeatures As Long
    Dim FID As String
    '
    '-----------------------
    'INITIALIZATION of Global Variable(s)
    '-----------------------
    CurrentNetFeatures = 1
    TotalNetFeatures = 0
    FID = " " 'Feature ID
    '
    '==================
    Sub GetNetData()
    '==================
    Dim App As Object
    Dim Part As Object
    Dim Cmds As Object
    Set App = CreateObject("PCDLRN.Application")
    Set Part = App.ActivePartProgram
    Set Cmds = Part.Commands
    Dim Cmd As Object
    Dim I As Long
    '
    I = 1
        For Each Cmd In Cmds
            If Cmd.isFeature And Cmd.Feature = F_POINT  Then
                FID = Cmd.ID
                If InStr(1, FID,"NET") <> 0 Then
                    NetData(I,1) = Cmd.GetText(THEO_X,0)
                    NetData(I,2) = Cmd.GetText(THEO_Y,0)
                    NetData(I,3) = Cmd.GetText(THEO_Z,0)
                    NetData(I,4) = Cmd.GetText(MEAS_X,0)
                    NetData(I,5) = Cmd.GetText(MEAS_Y,0)
                    NetData(I,6) = Cmd.GetText(MEAS_Z,0)
                    NetData(I,7) = Cmd.GetText(MEAS_I,0)
                    NetData(I,8) = Cmd.GetText(MEAS_J,0)
                    NetData(I,9) = Cmd.GetText(MEAS_K,0)
                    NetData(I,10) = FID
                    TotalNetFeatures = I
                    I = I + 1
                End If
            End If
        Next Cmd
    End Sub
    '
    '==================
    Sub LoadLine()
    '==================
    Dim App As Object
    Dim Part As Object
    Dim Cmds As Object
    Dim LastCmd As Object
    '
    Set App = CreateObject("PCDLRN.Application")
    Set Part = App.ActivePartProgram
    Set Cmds = Part.Commands
    '
    Dim Cmd As Object
    Dim RetVal As Boolean
    Dim RefId1, Refld2, XT, YT, ZT, DIRX, DIRY, DIRZ As String
    Dim FeatureName As String
    '
    Dim CommandCount As Long
    '
        CommandCount = Cmds.count
        XT = NetData(1,4)
        YT = NetData(1,5)
        ZT = NetData(1,6)
        DIRX = NetData(1,7)
        DIRY = NetData(1,8)
        DIRZ = NetData(1,9)
        FeatureName = "LIN1"
        For Each Cmd In Cmds
            If Cmd.isFeature And Cmd.Feature = F_LINE Then
                Cmd.Marked = True
                RetVal = Cmd.SetToggleString(1, COORD_TYPE, 0)
                RetVal = Cmd.PutText(NetData(CurrentNetFeature,4), THEO_SX, 0)
                RetVal = Cmd.PutText(NetData(CurrentNetFeature,5), THEO_SY, 0)
                RetVal = Cmd.PutText(NetData(CurrentNetFeature,6), THEO_SZ, 0)
                RetVal = Cmd.PutText(NetData(CurrentNetFeature,4), THEO_EX, 0)
                RetVal = Cmd.PutText(NetData(CurrentNetFeature,5), THEO_EY, 0)
                RetVal = Cmd.PutText(NetData(CurrentNetFeature,6), THEO_EZ, 0)
                RetVal = Cmd.PutText(NetData(CurrentNetFeature,7), THEO_I, 0)
                RetVal = Cmd.PutText(NetData(CurrentNetFeature,8), THEO_J, 0)
                RetVal = Cmd.PutText(NetData(CurrentNetFeature,9), THEO_K, 0)
                RetVal = Cmd.PutText("0", THEO_LENGTH, 0)
                RetVal = Cmd.PutText("0", SURFVEC_I, 0)
                RetVal = Cmd.PutText("0", SURFVEC_J, 0)
                RetVal = Cmd.PutText("1", SURFVEC_K, 0)
    
                RetVal = Cmd.PutText(NetData(CurrentNetFeature,4), MEAS_SX, 0)
                RetVal = Cmd.PutText(NetData(CurrentNetFeature,5), MEAS_SY, 0)
                RetVal = Cmd.PutText(NetData(CurrentNetFeature,6), MEAS_SZ, 0)
                RetVal = Cmd.PutText(NetData(CurrentNetFeature,4), MEAS_EX, 0)
                RetVal = Cmd.PutText(NetData(CurrentNetFeature,5), MEAS_EY, 0)
                RetVal = Cmd.PutText(NetData(CurrentNetFeature,6), MEAS_EZ, 0)
                RetVal = Cmd.PutText(NetData(CurrentNetFeature,7), MEAS_I, 0)
                RetVal = Cmd.PutText(NetData(CurrentNetFeature,8), MEAS_J, 0)
                RetVal = Cmd.PutText(NetData(CurrentNetFeature,9), MEAS_K, 0)
                RetVal = Cmd.PutText("0", MEAS_LENGTH, 0)
                RetVal = Cmd.PutText("0", SURFVEC_MEAS_I, 0)
                RetVal = Cmd.PutText("0", SURFVEC_MEAS_J, 0)
                RetVal = Cmd.PutText("1", SURFVEC_MEAS_K, 0)
                RetVal = Cmd.PutText(FeatureName, ID, 0)
            End If
        Next Cmd
    '
    End Sub
    '
    '==================
    Sub CreateDrop()
    '==================
        Dim App As Object
        Dim Part As Object
        Dim Cmds As Object
        Dim DmisCmd As Object
    '
        Set App = CreateObject("PCDLRN.Application")
        Set Part = App.ActivePartProgram
        Set Cmds = Part.Commands
    '
        Dim RetVal As Boolean
        Dim RefId1, Refld2, XT, YT, ZT As String
        Dim DropFeatureName, FID As String
        Dim CommandCount As Long
    '
        CommandCount = Cmds.count
        Set DmisCmd = Cmds.Item(CommandCount)
    '
        For Each DmisCmd In Cmds
    '        If DmisCmd.isFeature And DmisCmd.Feature = F_LINE  Then
            If DmisCmd.isFeature And DmisCmd.Feature = 4 Then
                RefId1 = NetData(CurrentNetFeature,10)
                RefId2 = "LIN1"
                DropFeatureName = "CDROP" + NetData(CurrentNetFeature,10)
                Cmds.InsertionPointAfter DmisCmd
                Set DmisCmd= Cmds.Add(CONST_DROP_POINT, True)
                DmisCmd.Marked = True
                RetVal = DmisCmd.PutText(DropFeatureName, ID, 0)
                RetVal = DmisCmd.PutText(RefId1, REF_ID, 1)
                RetVal = DmisCmd.PutText(RefId2, REF_ID, 2)
                RetVal = DmisCmd.SetToggleString(1, COORD_TYPE, 0)
    '            XT = DmisCmd.GetText(THEO_X, 0)
                NetData(CurrentNetFeature,1) = DmisCmd.GetText(THEO_X, 0)
    '            YT = DmisCmd.GetText(THEO_Y, 0)
                NetData(CurrentNetFeature,2) = DmisCmd.GetText(THEO_Y, 0)
    '            ZT = DmisCmd.GetText(THEO_Z, 0)
                NetData(CurrentNetFeature,3) = DmisCmd.GetText(THEO_Z, 0)
            End If
        Next DmisCmd
    End Sub
    '
    '==================
    Sub WriteNominals()
    '==================
    Dim App As Object
    Dim Part As Object
    Dim Cmds As Object
    Dim LastCmd As Object
    '
    Set App = CreateObject("PCDLRN.Application")
    Set Part = App.ActivePartProgram
    Set Cmds = Part.Commands
    '
    Dim PrgLineCmd As Object
    Dim RetVal As Boolean
    Dim RefId1, Refld2, XT, YT, ZT, DIRX, DIRY, DIRZ As String
    Dim FeatureName As String
    '
        For Each PrgLineCmd In Cmds
            If PrgLineCmd.isFeature Then
                FID = PrgLineCmd.ID
                If FID = NetData(CurrentNetFeature,10) Then
                    PrgLineCmd.Marked = True
                    RetVal = PrgLineCmd.PutText(NetData(CurrentNetFeature,1), THEO_X, 0)
                    RetVal = PrgLineCmd.PutText(NetData(CurrentNetFeature,2), THEO_Y, 0)
                    RetVal = PrgLineCmd.PutText(NetData(CurrentNetFeature,3), THEO_Z, 0)
                End If
            End If
        Next PrgLineCmd
    End Sub
    '
    '==================
    Sub GetProjectPointData()
    '==================
    Dim App As Object
    Dim Part As Object
    Dim Cmds As Object
    '
    Set App = CreateObject("PCDLRN.Application")
    Set Part = App.ActivePartProgram
    Set Cmds = Part.Commands
    '
    Dim GWindow As Object
    Dim CadWin As Object
    Set GWindow = Part.CadWindows
    Set CadWin = GWindow.Item(1)
    CadWin.Visible = True
    '
    Dim CADMod As CadModel
    Set CADMod = Part.CadModel
    Dim XM, YM, ZM, DIRX, DIRY, DIRZ, PX, PY, PZ, PDIRX, PDIRY, PDIRZ As Double
    Dim FeatureName As String
    Dim RetVal As Boolean
    RetVal = CadWin.Visible
    '
    XM=NetData(6,1)
    YM=NetData(6,2)
    ZM=NetData(6,3)
    Dim CH As Integer
    Dim CadResult As Integer
    '
    ' 7 All Cad Features
    ' 4 Cad Surfaces Only
    '
          CadResult = CADMod.CADProjectPoint(XT, YT, ZT,4,0,0, PX, PY, PZ, PDIRX, PDIRY, PDIRZ, CH)
    '
    ' -1  Invalid Object handle, Or operation Not enabled; no value returned.
    '  0  No value returned; geometry doesn't make sense, failed geometry (i.e. parallel lines), Or Not yet implemented.
    '  2  Logic produced a hit, value returned (all is well).
    '  1  Logic produced a miss, closest point returned Or ambiguous point returned.
    '
    End Sub
    '
    '==================
    Sub Main()
    '==================
    Dim App As Object
    Dim Part As Object
    Dim Cmds As Objec
    '
    Set App = CreateObject("PCDLRN.Application")
    Set Part = App.ActivePartProgram
    Set Cmds = Part.Commands
    '
    Dim RepWin As Object
    Set RepWin = Part.ReportWindow
    Dim EditWin As Object
    Set EditWin = Part.EditWindow
    EditWin.Visible = True
    '
        GetNetData
        For CurrentNetFeature = 1 To TotalNetFeatures
            LoadLine
            CreateDrop
            WriteNominals
        Next CurrentNetFeature
        GetProjectPointData
    '
    Part.Activate
    EditWin.Visible = True
    End Sub
    
    


  • Finding Other Possibilities:
    Upon further investigation I came across the "View Menu/Cad Verify" option in PC-DMIS. Looking at this, I plugged in my drop_point constructed nominals from my script and the Cad Verify menu produced the exact nominals seen in the "OverRide Nominals" window when a point is bumped. It actually shows both nominals and vector from the point projected onto the Cad Model. Looking further, I found that the object CadModel.CADProjectPoint is the object that will produce the same results as the Cad Verify menu produces.

    Current Script Condition:
    As of now, I am unable to get CadModel.CADProjectPoint to work. This function has type ENUM_CAD_RESULT. Clicking on this in the help menus show that the values are -1, 0, 2, and 1. This would suggest that the function should be assigned to an Integer value (as seen in the script).

    Other questions I have pertain to the last returned value "CadHandle". CadHandle is an object that, as far as I can tell, seems to represent an instance of the Cad Model in the Graphics Dislpay Window (could be wrong about this) and somehow must be defined prior to using CadModel.CADProjectPoint. The members are CadSequence, Collection, PartInstanceID, and SubCadId. Funny there is no description for CadHandle and not much in the way of showing how it is used.

    Also seeing a ENUM_CAD_COLLECTION. Each of these members starts with HCAD_. Because I am dealing with projecting points onto cad surfaces, HCAD_SURFACE (value = 1) may be my best bet when defining CadHandle.collection.

    Notes on LoadLine:
    I am currently importing the line feature I use to load each measured feature's value in to it. Tried creating it in the script but I must be missing something because the script created line does not produce the drop_point values seen when I import/dmis line. Here's the .dmi file I import below my net pad hits (10 total);

     DMISMN/LIN1.dmi
     FILNAM/LIN1.dmi
    F(LIN1)=FEAT/MEAS_LINE,UNBND,CART,722.23,760.92,1593.72,0.9999999,0.0002614,$
      -0.0002259,0,0,1
    MEAS/LINE,F(LIN1),2
        PTMEAS/CART,0,0,0,0,0,1,RMS=N/A,
        PTMEAS/CART,0,0,0,0,0,1,RMS=N/A,
    ENDMES
    ENDFIL
    


    Any further thought would be appreciated pertaining to the script set-up procedure for accessing the cad model in the Graphics Display Window or the use of object CadModel.CADProjectPoint.

    Alien​​​​​​​​​​​​​​
  • Nice job especially on a rare use of multidimensional array! Love that you have to allocate memory to them Rolling eyes
    Appreciate you sharing with the community.
  • The script I'm writing to try and access the Graphics Display Window where my cad model resides pertains to me wanting to "OverRide Nominals" of points I measured using our Laser Tracker. After measuring net pads (we take 5 hits (vector_points) on each pad) on our tooling here at Fiat-Chrysler Automobiles, we have to go back and bump each point measured against the cad mode in the Graphics Display Window to aquire the proper nominal value for each point.


    I may be misunderstanding something, but isn't that what "Find Nominals during Execution" does? F5, General, ~2 pages down through the check boxes.

  • Response #10:
    AndersI, I did a test and no luck. We are in manual mode, learning each point into the program as we measure manually on the tooling. After learning 5 hit points on a net pad, I re-executed the points and re-measured them individually. The THEO's picked up in the measured hit does not match the THEO seen in the OverRide Nominals Window when I bump the point to CAD model in Graphics Display Window.

    Could it be possible that the "Find Nominal on Execution" is for Scanning? I'm not sure myself seeing as I have not done any scanning to see how this works with scans. It doesn't appear to work (pick up nominals from cad model) using our Tracker Software.

    I guess my real issue is still 'Trying to access the CAD model in the Graphics Display Window' using a basic script. I can access the Edit Window features and even refresh the Report Window through commands in my script, but haven't figured out how to access the GDWindow.

    The CadModel Object description is:

    "The CadModel object allows you to work with the imported CAD model in PC-DMIS' Graphic Display Window".

    I haven't seen anywhere (Internet, pcdmis forum, etc...) where someone has the basic script calls to access the GDWindow. I have been in contact with Hexagon here in Michigan. Will give them a call back today and see if they can push this to a higher level to see if someone knows how to do this through a script. Not sure if the type declarations are correct in these CadModel Methods are correct and certainly not sure about the CadHandle Object and how that intertwines into all of this.

    Still in Limbo here at FCA, Alien