Andreas
Andreas

Reputation: 63

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

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.

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

Upvotes: 0

Views: 81

Answers (0)

Related Questions