CadQuery / OCP

Apache License 2.0
90 stars 27 forks source link

TDF_Label.FindAttribute is not updating handle with the found attribute values #55

Closed echeng22 closed 2 years ago

echeng22 commented 3 years ago

Hi, I'm running into an issue where the FindAttribute() function under TDF_Label does not update the TDF_Attribute handle passed to it. I've attached the script, and files in the zip file of an example.

Relevant snippet of the script:

            # Handle to the TDataStd_Name Attribute
            label_attr = TDataStd.TDataStd_Name()

            if label.FindAttribute(label_attr.GetID_s(), label_attr):
                output = self.stream()
                print(f"label_name found {label_attr}")
                label_attr.DumpJson(output)
                print(f"Label Attr JSON Dump: {output.getvalue()}\n")

                expected_name = label_attr.Get()
                output = self.stream()
                expected_name.Print(output)
                print(f"Attribute name: {output.getvalue()} \n")

The output of the script is attached below:

Number of shapes at root: 1
Number of shapes at root: 1
Save results: PCDM_StoreStatus.PCDM_SS_OK
item 0
label: <OCP.TDF.TDF_Label object at 0x7f8d051b7230>

Label Dump: b'0:1:1:1'

label_name found <OCP.TDataStd.TDataStd_Name object at 0x7f8d05429b70>
Label Attr JSON Dump: b'"className": "TDataStd_GenericExtString""className": "TDF_Attribute""Label": """Transaction": 0"SavedTransaction": 0"Flags": 1"Get": """ID": "2a96b608-ec8b-11d0-bee7-080009dc3333"'

Attribute name: b'' 

I would expect the Attribute name to return SOLID, based off what the test_input.stp and test_input.xml is showing for this label, but that doesn't seem to be the case here. Is there something that I'm missing to get the result I want?

input_files.zip

adam-urbanczyk commented 3 years ago

Confirmed, this is an OCP issue.

Also reported here: https://github.com/CadQuery/cadquery/issues/825

adam-urbanczyk commented 3 years ago

For now, the workaround would be to use OCP.TDF.TDF_AttributeIterator and find the attribute by hand. This means essentially re-implementing FindAttribute by hand.

See: https://github.com/Open-Cascade-SAS/OCCT/blob/cb7f92396f80270e13206be742038ca0ce04571a/src/TDF/TDF_Label.cxx#L64

adam-urbanczyk commented 3 years ago

Relevant pybind11 issues: https://github.com/pybind/pybind11/issues/1320 https://github.com/pybind/pybind11/issues/2751

echeng22 commented 3 years ago

Great! Thanks for the follow up and suggestion. I'll take a look through and see what I can do with it.

adam-urbanczyk commented 3 years ago

Something along those lines:

i = OCP.TDF.TDF_AttributeIterator(l)
v = i.Value()
while i.More(): 
    i.Next()
...
echeng22 commented 3 years ago

Got it to work with this for name attribute specifically. Can be easily updated to search for other attributes as needed. Sharing this here in case it's of any help for other people.

def find_name(label: TDF.TDF_Label) -> TDataStd.TDataStd_Name:

    label_it = TDF.TDF_AttributeIterator(label)
    while label_it.More():
        attr = label_it.Value()
        if Standard.Standard_GUID.IsEqual_s(
            attr.ID(), TDataStd.TDataStd_Name.GetID_s()
        ):
            return attr
        label_it.Next()

Thanks again for the help on this.

adam-urbanczyk commented 3 years ago

@a09418849 take a look at the workaround.