Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to work with Attributes and Labels in pythonocc-core compared to c++? #1368

Open
andreaswatch opened this issue Sep 7, 2024 · 0 comments

Comments

@andreaswatch
Copy link

Note: The same question has also been asked on stackoverflow, but has not yet been answered. ( https://stackoverflow.com/questions/78954992 )

I have problems understanding Labels and Attributes in pythonocc-core.

The code outputs the result of getVersion() before and after a call to setVersion(123).
For debugging, getVersion returns 99 if no value is found. -1 is returned as error for invalid attributes.

print("The version is:", self.get_version())
self.set_version(123)
print("The version is:", self.get_version())

Expected output:

The version is: 99
The version is: 123

Output python:

The version is: 99
The version is: -1

The idea is that the "version" value should be stored using a TDataStd_Integer the documents main label.
The getVersion and setVersion methods call into get_version_attribute to either get or create the attribute that is used to store the value.
Anyway, in pythonocc-core it looks like that the FindAttribute method returns a bad (None) attribute when it actually finds an Attribute. Am I using it wrong?

Python Implementation:

class DocumentEditor:
    def __init__(self):
        # Initialize application and create a new document
        self._app = XCAFApp_Application.GetApplication()
        self._doc = TDocStd_Document("format")
        self._app.NewDocument("format", self._doc)

        print("The version is:", self.get_version())
        self.set_version(123)
        print("The version is:", self.get_version())

    def get_version_data(self):
        # Create a new attribute
        data = TDataStd_Integer()
        uuid = TDataStd_Integer.GetID()
        data.SetID(uuid)
        return data

    def get_version_attribute(self):
        label = self._doc.Main()
        attribute = TDataStd_Integer()

        if label.FindAttribute(TDataStd_Integer.GetID(), attribute):
            return attribute #this attribute seems to be bad in pythonocc-core

        # Attribute not found, create a new one, add to the label and initialize
        attribute = self.get_version_data()
        label.AddAttribute(attribute)
        attribute.Set(99)  # for debugging only!
        return attribute

    def set_version(self, version):
        attribute = self.get_version_attribute()
        attribute.Set(version)

    def get_version(self):
        attribute = self.get_version_attribute()
        if attribute is None:
            return -1  # error
        return attribute.Get()

DocumentEditor()

For testing purposes I have implemented the same methods in cpp, the code is very close to the python version.
The cpp version shows the expected output.

C++ Implementation:

#include <BRepPrimAPI_MakeBox.hxx>
#include <GProp_GProps.hxx>
#include <BRepGProp.hxx>
#include <gp_Pnt.hxx>
#include <Standard_Real.hxx>
#include <iostream>

#include "vcpkg_installed/x64-linux/include/opencascade/TDocStd_Document.hxx"
#include "vcpkg_installed/x64-linux/include/opencascade/XCAFApp_Application.hxx"
#include "vcpkg_installed/x64-linux/include/opencascade/TDataStd_Integer.hxx"
#include <string>

class DocumentEditor {

private:
    Handle(XCAFApp_Application) _app;
    Handle(TDocStd_Document) _doc;

public:
    DocumentEditor() {
        // Initialize application and create a new document
        _app = XCAFApp_Application::GetApplication();
        _app->NewDocument(TCollection_ExtendedString("format"), _doc);

        std::cout << "The version is: " << GetVersion() << std::endl;
        SetVersion(123);
        std::cout << "The version is: " << GetVersion() << std::endl;
    }

private:
    Handle(TDataStd_Integer) GetVersionData() {
        // Create a new attribute
        Handle(TDataStd_Integer) data = new TDataStd_Integer();
        Standard_GUID uuid = TDataStd_Integer::GetID();
        data->SetID(uuid);
        return data;
    }

    Handle(TDataStd_Integer) GetVersionAttribute() {
        
        TDF_Label label = _doc->Main();
        Handle(TDataStd_Integer) attribute;

        if (label.FindAttribute(TDataStd_Integer::GetID(), attribute)) {
            return attribute;
        }

        // Attribute not found, create a new one, add to the label and initialize
        attribute = GetVersionData();
        label.AddAttribute(attribute);
        attribute->Set(99); // for debugging only!
        return attribute;
    }

    void SetVersion(int version) {
        Handle(TDataStd_Integer) attribute = GetVersionAttribute();
        attribute->Set(version);
    }

    int GetVersion() {
        Handle(TDataStd_Integer) attribute = GetVersionAttribute();
        if (attribute.IsNull()) {
            return -1; // error
        }
        return attribute->Get();
    }
};

I'm wondering if this is a problem with the non-existent handles in pythonocc-core?
Is there another way to embed user-defined data in a document?

Any useful suggestions and codes would be appreciated!
Thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant