Skip to content

Commit 166f7f5

Browse files
Merge pull request #198 from CRIStAL-PADR/pr-add-createobject-behavior
[SofaPython3] Changes how addObject process its arguments when they are of type: numpy & data
2 parents f1140e9 + 44dbe9c commit 166f7f5

File tree

7 files changed

+49
-4
lines changed

7 files changed

+49
-4
lines changed

Plugin/src/SofaPython3/DataHelper.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,20 @@ std::string toSofaParsableString(const py::handle& p)
4848
if(py::isinstance<py::str>(p))
4949
return py::str(p);
5050

51-
// Insure compatibility with data field code returning value instead of data.
51+
// If the object is a data field we link the data field
5252
if(py::isinstance<sofa::core::objectmodel::BaseData>(p))
5353
{
5454
sofa::core::objectmodel::BaseData* data = py::cast<sofa::core::objectmodel::BaseData*>(p);
5555
return data->getValueString();
5656
}
57+
58+
// If the object is a numpy array we convert it to a list then to a sofa string.
59+
if(py::isinstance<py::array>(p))
60+
{
61+
py::object o = p.attr("tolist")();
62+
return toSofaParsableString(o);
63+
}
64+
5765
return py::repr(p);
5866
}
5967

bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Base.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,13 @@ std::string BindingBase::getPathName(Base& self)
387387
{
388388
return self.toBaseNode() ? self.toBaseNode()->getPathName() : self.toBaseObject()->getPathName();
389389
}
390-
390+
391+
std::string BindingBase::getLinkPath(Base& self)
392+
{
393+
return "@"+getPathName(self);
394+
}
395+
396+
391397
py::object BindingBase::setDataValues(Base& self, py::kwargs kwargs)
392398
{
393399
for(auto key : kwargs)
@@ -435,7 +441,8 @@ void moduleAddBase(py::module &m)
435441
base.def("getLoggedMessagesAsString", &BindingBase::getLoggedMessagesAsString, sofapython3::doc::base::getLoggedMessagesAsString);
436442
base.def("countLoggedMessages", &BindingBase::countLoggedMessages, sofapython3::doc::base::countLoggedMessages);
437443
base.def("clearLoggedMessages", &BindingBase::clearLoggedMessages, sofapython3::doc::base::clearLoggedMessages);
438-
base.def("getPathName", &BindingBase::getPathName);
444+
base.def("getPathName", &BindingBase::getPathName, sofapython3::doc::base::getPathName);
445+
base.def("getLinkPath", &BindingBase::getLinkPath, sofapython3::doc::base::getLinkPath);
439446
base.def("setDataValues", &BindingBase::setDataValues, sofapython3::doc::base::setDataValues);
440447
}
441448

bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Base.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ class BindingBase
6464
static pybind11::object countLoggedMessages(sofa::core::objectmodel::Base& self);
6565
static pybind11::object clearLoggedMessages(sofa::core::objectmodel::Base& self);
6666
static std::string getPathName(sofa::core::objectmodel::Base& self);
67+
static std::string getLinkPath(sofa::core::objectmodel::Base& self);
6768
};
6869

6970

bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseData.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ py::object writeableArray(BaseData* self)
112112

113113
void __setattr__(py::object self, const std::string& s, py::object value)
114114
{
115+
SOFA_UNUSED(s);
115116
BaseData* selfdata = py::cast<BaseData*>(self);
116117

117118
if(py::isinstance<DataContainer>(value))
@@ -137,6 +138,9 @@ py::object __getattr__(py::object self, const std::string& s)
137138
if(s == "value")
138139
return PythonFactory::valueToPython_ro(py::cast<BaseData*>(self));
139140

141+
if(s == "linkpath")
142+
return py::cast((py::cast<BaseData*>(self))->getLinkPath());
143+
140144
/// BaseData does not support dynamic attributes, if you think this is an important feature
141145
/// please request for its integration.
142146
throw py::attribute_error("There is no attribute '"+s+"'");

bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_Base_doc.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,22 @@ static auto findData =
6363
:type name: string
6464
:return: the data field
6565
)";
66+
static auto getLinkPath =
67+
R"(
68+
returns the path name as a parsable string.
69+
eg:
70+
if object.getPathName() is "/child1/object"
71+
then the linkPath is @"/child1/object"
72+
)";
73+
static auto getPathName =
74+
R"(
75+
returns the path name as a string.
76+
.. code-block:: python
77+
a = Sofa.Core.Node("root")
78+
b.addObject("Camera", name="camera")
79+
b.getPathName() # should returns "/root/camera"
80+
```
81+
)";
6682
static auto setDataValues =
6783
R"(
6884
Set values for a the given data field, multiple pairs of args are allowed.

bindings/Sofa/tests/Core/Base.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,11 @@ def test_getTemplateName(self):
123123
c = root.addObject("MechanicalObject", name="t")
124124
self.assertEqual(c.getTemplateName(),"Vec3d")
125125

126-
126+
def test_getLinkPath(self):
127+
root = create_scene("root")
128+
obj = root.addObject("MechanicalObject", name="obj")
129+
self.assertEqual(obj.getPathName(),"/obj")
130+
self.assertEqual(obj.getLinkPath(),"@/obj")
127131

128132
def test_addExistingDataAsParentOfNewData(self):
129133
# TODO(@marques-bruno)

bindings/Sofa/tests/Core/BaseData.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,11 @@ def t(c):
292292
self.assertEqual(wa[2, 2], 8.0)
293293
numpy.testing.assert_array_equal(wa, v*4.0)
294294

295+
def test_linkpath(self):
296+
n = create_scene("rootNode")
297+
m = n. addObject("MechanicalObject", name="dofs")
298+
self.assertEqual(m.position.linkpath, "@/dofs.position")
299+
295300
def test_set_value_from_string(self):
296301
n = create_scene("rootNode")
297302
n.gravity.value = [1.0,2.0,3.0]

0 commit comments

Comments
 (0)