Using ReferenceKeys to match a Copy Object Face with the Source Face

Using ReferenceKeys to match a Copy Object Face with the Source Face

Anonymous
Not applicable
1,418 Views
13 Replies
Message 1 of 14

Using ReferenceKeys to match a Copy Object Face with the Source Face

Anonymous
Not applicable

I'm trying to use ReferenceKeys to match a Copy Object Face with the Source Face in the source part. The code below does not seem to show any matching Reference keys,

 

 

 

Imports System.Runtime.InteropServices
Imports System.IO
Imports Inventor

Public Module modReferenceKeys
    ' Name of the file for saving reference keys
    Private _Filename As String = "c:\temp\keydata.txt"

    Public Sub GetKeys(CopyObjectComponent As ComponentOccurrence, SourceComponent As ComponentOccurrence)

        Dim oDoc As PartDocument = CopyObjectComponent.Definition.Document()
        Dim oDef As PartComponentDefinition = oDoc.ComponentDefinition
        Dim oRefKeyMgr As ReferenceKeyManager = oDoc.ReferenceKeyManager

        Dim oScupltDoc As PartDocument = SourceComponent.Definition.Document()
        Dim oSculptDef As PartComponentDefinition = oScupltDoc.ComponentDefinition
        Dim oSculptRefKeyMgr As ReferenceKeyManager = oScupltDoc.ReferenceKeyManager

        ' The keys will be written to binary file for later access
        Dim binWriter As New BinaryWriter( _
            System.IO.File.Open(_Filename, FileMode.Create))
        Try
            Dim lContext As Long
            Dim byContext() As Byte = New Byte() {}  ' initilization
            ' The conext should be created only once
            lContext = oRefKeyMgr.CreateKeyContext

            Dim lSculptContext As Long
            Dim bySculptContext() As Byte = New Byte() {}  ' initilization
            ' The conext should be created only once
            lSculptContext = oSculptRefKeyMgr.CreateKeyContext

            ' Dump the number of faces in this model
            binWriter.Write(oDef.Features.NonParametricBaseFeatures(1).Faces.Count())
            binWriter.Write(Chr(13))
            binWriter.Write(oSculptDef.Features.KnitFeatures(1).Faces.Count())
            binWriter.Write(Chr(13))
            ' Iterate through all faces and dump key
            Dim oFace As Face
            For Each oFace In oDef.Features.NonParametricBaseFeatures(1).Faces

                ' get key from oFace
                Dim byKey() As Byte = New Byte() {}
                oFace.GetReferenceKey(byKey, lContext)


                Dim oSculptFace As Face
                For Each oSculptFace In oSculptDef.Features.KnitFeatures(1).Faces

                    ' get key from oFace
                    Dim byScupltKey() As Byte = New Byte() {}
                    oSculptFace.GetReferenceKey(byScupltKey, lSculptContext)

                    If byScupltKey Is byKey Then
                        binWriter.Write("YAY They Matched!!!!!!!!!!")
                        binWriter.Write(Chr(13))
                    End If
                    ' save the key size and key in the file
                    'binWriter.Write(Chr(13))
                    'binWriter.Write("-----------------------------------")
                    'binWriter.Write(Chr(13))
                    'binWriter.Write(byKey.Length)
                    'binWriter.Write(Chr(13))
                    'binWriter.Write(byKey)
                    'binWriter.Write(Chr(13))
                    'binWriter.Write(byKey.ToString())
                    'binWriter.Write(Chr(13))
                    'binWriter.Write(byScupltKey.Length)
                    'binWriter.Write(Chr(13))
                    'binWriter.Write(byScupltKey)
                    'binWriter.Write(Chr(13))
                    'binWriter.Write(byScupltKey.ToString())
                    'binWriter.Write(Chr(13))
                    'binWriter.Write("-----------------------------------")
                    'binWriter.Write(Chr(13))
                    'End If

                Next

            Next
            ' We have finished creating all the keys,
            ' now save the long context as byte array
            ' Context should be saved after creating all the keys
            oRefKeyMgr.SaveContextToArray(lContext, byContext)
            ' Dump the size and context array into file
            binWriter.Write(byContext.Length)
            binWriter.Write(Chr(13))
            binWriter.Write(byContext.ToString())
            binWriter.Write(Chr(13))
        Catch ex As SystemException
            MsgBox(ex.ToString())
        Finally
            binWriter.Close()
            MsgBox("Reference Keys are Saved in the file:" & vbNewLine & _Filename)
        End Try
        oRefKeyMgr = Nothing
        oDoc = Nothing
    End Sub 'GetKeys
End Module

I got the original code form here: Maintaining persistent links to objects across Inventor sessions using ReferenceKeys

 

I using Inventor 2016 

 

Thanks,

 

0 Likes
1,419 Views
13 Replies
Replies (13)
Message 2 of 14

adam.nagy
Autodesk Support
Autodesk Support

Hi Justin,

 

Are you talking about getting the face corresponding to the one it is derived from?

You could use the Face's ReferencedEntity property:

http://adndevblog.typepad.com/manufacturing/2014/11/get-edge-in-derived-part-that-drives-work-point....

 

ReferenceKeys are context sensitive. So if you check the reference key of a face in a part then it will be different in the assembly where it is inserted, since the same face could show up multiple times in the assembly if the part is inserted multiple times, so how could you find a specific face then?

So that's not the way to go if that's the scenario where you are trying to use them.

 

Cheers,



Adam Nagy
Autodesk Platform Services
0 Likes
Message 3 of 14

Anonymous
Not applicable

Yes I am trying to match the face of a copy object with the face of the part is was derived from.  However,  I do not want the copy object associative with the derived part.

0 Likes
Message 4 of 14

adam.nagy
Autodesk Support
Autodesk Support

First of all, might be worth reading through the "Reference Keys" section in this document in case you haven't done it already:

http://aucache.autodesk.com/au2012/sessionsFiles/3547/4363/handout_3547_CP3547-InventorAPIOddsAndEnd...

 

Do I understand that correctly that you have a part in an assembly and on one of the occurrences you clicked "Component >> Copy"?

Has the copied part document been modified since the copy or they are still exactly the same?

 

My understanding is that the context is like a snapshot of what geometry is available in the part and how it's organized. So if the part got modified the context will be different and so you can get different keys for the "same" face.

But I think that if the original part has not been modified then you could get a context there and a key for the face you are inetersted in, and then load that context into the copied document and try to retrieve the face based on the key you got. I think that should give you back the face you want. 

 

If I'm misudnerstanding the scenario then could you please provide the exact steps the relevant files go through from scratch?: 

1) create part 1

2) add it to asm1

3) etc

 



Adam Nagy
Autodesk Platform Services
0 Likes
Message 5 of 14

Anonymous
Not applicable

Ultimately what I am try to do is identify the source face for the Stitch Feature in the "Void.ipt" to the resulting face of the Scupt feature in the "box.ipt"

 

The process I following is as follows:

  1. Create the Assembly
  2. Copy the Stich features from the "Void.ipt" to the "Box.ipt" using Copy Object with the Associtative option turned offCopy Object.png
  3. Scuplt removing the geometery of the Copy Object.
  4. Scupt.png

 

NOTE: In some cases the source face get split into 2 faces.

 

 

Faces.png

0 Likes
Message 6 of 14

adam.nagy
Autodesk Support
Autodesk Support

Thanks for the files and the additional info.

 

Hmm, I'm not sure how you could take advantage of reference keys in this case, because I don't think that's what they are for.

Brian just blogged about references: http://modthemachine.typepad.com/my_weblog/2015/09/understanding-reference-keys-in-inventor.html

 

Under the "Important Points" section it says:

- A reference key context and reference keys will only work with the same document 
they were originally obtained from.
- Reference keys will only work with the same reference key context they were originally created with.

But in your case you are moving things around, so not trying to get things back in the same document.

 

I'm asking for comments from others about this though.

 

 



Adam Nagy
Autodesk Platform Services
0 Likes
Message 7 of 14

ekinsb
Alumni
Alumni

I believe what Adam has said is correct.  That reference keys are designed for this.  With the link broken there's no reason for Inventor to try and maintain any kind of logic between the original geometry and the new.

 

However, I think there is a reasonable solution.  It depends on the geometry in either the original part and the new not being modified, except for trimming.  It can't modified in a way that would change the position of the surfaces.  You can use the Face.PointOnFace property to get a coordinate that is on the new surface and then use the PartComponentDefinition.FindUsingPoint method to find the face in the original part that's at the same location.


Brian Ekins
Inventor and Fusion 360 API Expert
Mod the Machine blog
0 Likes
Message 8 of 14

ekinsb
Alumni
Alumni

Apparently after a certain amount of time you can no longer edit a post.  It was probably obvious from the rest of the post but the sentence towards the beginning should have said "That reference keys are NOT designed for this."


Brian Ekins
Inventor and Fusion 360 API Expert
Mod the Machine blog
0 Likes
Message 9 of 14

Anonymous
Not applicable

Brian,

 

I have never used the PartComponentDefinition.FindUsingPoint method before and I'm not really sure I understand the arguments.  This is what I have so far:

 

    Public Sub FaceNamingByPointOnFace(oSculptDef As PartComponentDefinition, SculptFeatureName As String, KnitDef As PartComponentDefinition)

        Dim oSculptFace As Face
        For Each oSculptFace In oSculptDef.Features.SculptFeatures(SculptFeatureName).Faces
            Dim SculptPoint As Point = oSculptFace.PointOnFace()
            Dim KnitFace As Face = KnitDef.FindUsingPoint(SculptPoint, Inventor.SelectionFilterEnum.kPartFaceFilter)
        Next
    End Sub

I'm getting this error from the selection filter I'm attempting to apply.

Selection Filter Error.png

 

Thanks

 

0 Likes
Message 10 of 14

ekinsb
Alumni
Alumni

There was one of the arguments that you had declared wrong and the output result.  It's an easy mistake to make but if you look closely at the help, it lists the type.  Here's a modified version of your function that should work.

 

Public Sub FaceNamingByPointOnFace(oSculptDef As PartComponentDefinition, SculptFeatureName As String, KnitDef As PartComponentDefinition)
    Dim oSculptFace As Face
    For Each oSculptFace In oSculptDef.Features.SculptFeatures(SculptFeatureNa​me).Faces
        Dim SculptPoint As Point = oSculptFace.PointOnFace()

        Dim filter(0) As Inventor.SelectionFilterEnum
        filter(0) = Inventor.SelectionFilterEnum.kPartFaceFilter
        Dim foundFaces As ObjectsEnumerator = KnitDef.FindUsingPoint(SculptPoint, filter, 0.001)
        Dim KnitFace As Face = foundFaces.Item(1)
    Next
End Sub

Brian Ekins
Inventor and Fusion 360 API Expert
Mod the Machine blog
0 Likes
Message 11 of 14

Anonymous
Not applicable

Brian,

 

Will the FindUsingPoint() method work on a PartCompentdefiniton that contains only surface bodies.  The knit featrure I'm using is in a part that does not contain any physical geometery.

 

Thanks,

0 Likes
Message 12 of 14

ekinsb
Alumni
Alumni
Yes it should work to find any faces regardless of whether they're part of a closed (solid) or open (surface) body.

Brian Ekins
Inventor and Fusion 360 API Expert
Mod the Machine blog
0 Likes
Message 13 of 14

Anonymous
Not applicable

I have attached an assembly and the part with no solid geometery with an iLogic rule (shown below) which raises the error below the code.  I have added a UCS to the assembly to veify the point is valid.

 

 

	Dim SculptPoint As Point = ThisApplication.TransientGeometry.CreatePoint(-28.831, -3.42, 152.4)

	doc = ThisDoc.Document
	Dim KnitCompOcc As ComponentOccurrence  = doc.ComponentDefinition.Occurrences.Item(1)
	Dim KnitCompDoc As PartDocument  = KnitCompOcc.Definition.Document
	Dim KnitCompDef As PartComponentDefinition = KnitCompDoc.ComponentDefinition
	

    Dim Filter(0) As Inventor.SelectionFilterEnum
    Filter(0) = Inventor.SelectionFilterEnum.kPartFaceFilter
	
	KnitCompDef.FindUsingPoint(SculptPoint, Filter, 0.001, False)

 

 

FindUsingPoint Error.png

0 Likes
Message 14 of 14

adam.nagy
Autodesk Support
Autodesk Support

Hi Justin,

 

I could not reproduce the issue in my Inventor 2016 Update2 with the files you provided - I simply got back nothing as a result, but no error.

 

And I get no result because the point coordinates are not provided correctly. Unlike iLogic functions, the Inventor API will always expect the coordinates in internal units: e.g. length is cm

http://adndevblog.typepad.com/manufacturing/2012/07/unitsofmeasure-object-and-example.html

 

If you check the values of the UCS object (e.g. in VBA Watches window) you'll see the same:

 

FindUsingPoint2.png

 

If I use those values (i.e. provide the coordinates in cm, then I'll find both faces which are touching that point:

'Dim SculptPoint As Point = ThisApplication.TransientGeometry.CreatePoint(-28.831, -3.42, 152.4)
Dim SculptPoint As Point = ThisApplication.TransientGeometry.CreatePoint(-73.23074, -8.6868, 387.096)

doc = ThisDoc.Document
Dim KnitCompOcc As ComponentOccurrence  = doc.ComponentDefinition.Occurrences.Item(1)
Dim KnitCompDoc As PartDocument  = KnitCompOcc.Definition.Document
Dim KnitCompDef As PartComponentDefinition = KnitCompDoc.ComponentDefinition
	
Dim Filter(0) As Inventor.SelectionFilterEnum
Filter(0) = Inventor.SelectionFilterEnum.kPartFaceFilter
	
Dim objs = KnitCompDef.FindUsingPoint(SculptPoint, Filter, 0.001, False)
	
MsgBox("Number of objects found = " + objs.Count.ToString())

FindUsingPoint1.png

 

Here is an article on converting from internal units to Document units:

http://adndevblog.typepad.com/manufacturing/2014/10/update-textbox-in-sketch.html

 

In case of your documents the part document is inserted at the origin of the assembly with the same orientation, so the transformation of the component occurrence is an identity matrix and so can be ignored. However, in situations when that is not the case it's worth knowing the following:

http://adndevblog.typepad.com/manufacturing/2013/07/occurrences-contexts-definitions-proxies.html 

 

Cheers, 



Adam Nagy
Autodesk Platform Services
0 Likes