8 Replies Latest reply on Feb 6, 2014 5:00 PM by Robert Owens

    Why is GetCoordinateSystemTransformByName() returning null?

    Robert Owens

      I was having issues using this function while passing a variable as the first input, so I decided to hard code in two of the coordinate systems to try and at least get something. However, both still return null! If I launch the measure tool interactively and select either Cube1Z's "Origin" or "Coordinate System1" feature, the names I have specified appear, so both match exactly.

       

      CComPtr<IModelDoc2> swModel;

      CComPtr<IModelDocExtension> swDocExt;

      CComPtr<IMathTransform> swXform;

      swModel->get_Extension(&swDocExt);

      swDocExt->GetCoordinateSystemTransformByName(L"Point1@Origin@Cube1Z-1@TestAssembly", &swXform);

      swDocExt->GetCoordinateSystemTransformByName(L"Coordinate System1@Cube1Z-1@TestAssembly", &swXform);

       

      Can anyone help shed some light on what is going on?

        • Re: Why is GetCoordinateSystemTransformByName() returning null?
          Artem Taturevych

          I suppose you can only get the transformation of coordinate system in its context. You cannot get the transformation of the CS which is in the part from the top assembly.

            • Re: Why is GetCoordinateSystemTransformByName() returning null?
              Robert Owens

              How is one supposed to get a transform from a part's CS relative to the top level assembly's origin? I'm assuming I'm simply using the wrong function, but searching the help keeps leading me back to this one.

                • Re: Why is GetCoordinateSystemTransformByName() returning null?
                  Simon Turner

                  Surely you just need Component2::Transform2 ?

                    • Re: Why is GetCoordinateSystemTransformByName() returning null?
                      Robert Owens

                      I had seen that, but I have an issue traversing the assembly to get the Component2 object.

                       

                      CComPtr<IComponent2> swComp;

                      CComPtr<IAssemblyDoc> swAsm;

                      CComPtr<IDispatch> D_vComps;

                      CComPtr<IMathTransform> swCompXForm;

                      VARIANT vComps;

                       

                      swAsm->GetComponents(false, &vComps);   // This returns an array of IDispatch, not IComponent2 as the help states

                      HRESULT CompArray = SafeArrayAccessData(vComps.parray, (void**)&D_vComps);  // Access the data in the array

                      for (int i=0; (sizeof(D_vComps)/sizeof(D_vComps[0])); i++)  // For each element in the array

                                {

                               HRESULT compOK = D_vComps[i].QueryInterface(IID_IComponent2, (void**)&swComp);  // ACCESS VIOLATION HERE

                                          swComp->get_Transform2(&swCompXForm);

                            }

                       

                      I have used QueryInterface at a different location to get IModelDocExtension from IDispatch without issue, but I'm not sure why I receive an access violation here.

                        • Re: Why is GetCoordinateSystemTransformByName() returning null?
                          Simon Turner

                          I tend not to use GetComponents. I use IGetChildren from IComponent2.

                           

                          You use ActiveConfiguration on the IConfigurationManager of the top level assemly to get an IConfiguration.

                          Then call GetRootComponent3 to get an IComponent2.

                          Finally call IGetChildren on that.

                          Works every time for me.

                            • Re: Why is GetCoordinateSystemTransformByName() returning null?
                              Robert Owens

                              This seems to be a much better route.. How do you set up the array of IComponent2's that IGetChildren returns? You run IGetChildrenCount to determine the size of the array, but what I have below throws the "no suitable conversion from std::vector to IComponent2 exists" error.

                               

                              int ChildrenCount;

                              CComPtr<IConfigurationManager> swConfigMgr;

                              CComPtr<IConfiguration> swConfig;

                              CComPtr<IComponent2> swComp;

                              swModel->get_ConfigurationManager(&swConfigMgr);

                              swConfigMgr->get_ActiveConfiguration(&swConfig);

                              swConfig->GetRootComponent3(true, &swComp);

                              swComp->IGetChildrenCount(&ChildrenCount);

                              std::vector<CComPtr<IComponent2>> swCompChildren(ChildrenCount);

                              swComp->IGetChildren(swCompChildren);

                               

                               

                              Without IGetChildrenCount and just doing the following returns a pointer to null:

                              CComPtr<IComponent2> swCompChildren;

                              swComp->IGetChildren(&swCompChildren);

                                • Re: Why is GetCoordinateSystemTransformByName() returning null?
                                  Simon Turner

                                  Sorry - I don't know enough about C++ to answer that. I use c# or VB - for exactly this sort of reason! You can spend longer sorting these casting problems out than writing the rest of the code.

                                  Anyway, I think you're on the right lines.  Hopefully someone else can solve the last part of the puzzle.

                                    • Re: Why is GetCoordinateSystemTransformByName() returning null?
                                      Robert Owens

                                      Just for the sake of completion... GetChildren() returns an array of IDispatch objects.You can access the array data via a SafeArray. You then use QueryInterface() to (in my interpretation) tell the system that the IDispatch object that swc[i] points to is an IComponent2 object. After that you can use the typical commands to calculate the transformation matrix.

                                       

                                      VARIANT swCompChildren;

                                      CComPtr<IComponent2>* swc;

                                      swComp->GetChildren(&swCompChildren);

                                      SAFEARRAY *psa = V_ARRAY(&swCompChildren);

                                      SafeArrayGetUBound(psa,1,&ChildrenCount);

                                      HRESULT CompArray = SafeArrayAccessData(swCompChildren.parray, (void**)&swc);

                                      for (int i=0; i<=ChildrenCount; i++)

                                      {

                                      CComPtr<IComponent2> swComponent;

                                      HRESULT compOK = swc[i]->QueryInterface(IID_IComponent2, (void**)&swComponent);

                                      ...

                                      }