Objects in compas_cloud

Does compas_cloud.Proxy already support sending and receiving objects? If not, are there any plans to support this?

AFAIR, the good ol’ compas_rpc.Proxy deals only with python native datatypes which, for example, makes users have to use force.data, form.data instead of FormDiagram, ForceDiagram with compas_tna when in Rhino.

Thanks!

good old RPC now supports all COMPAS objects without the need for explicit conversion…

import json
import compas
from compas.geometry import Point, Frame
from compas.datastructures import Mesh
from compas.utilities import DataEncoder, DataDecoder

point = Point(0, 0, 0)
frame = Frame.worldXY()
mesh = Mesh.from_obj(compas.get('faces.obj'))

data1 = [point, frame, mesh]

jsondata = json.dumps(data1, cls=DataEncoder)

data2 = json.loads(jsondata, cls=DataDecoder)

data1[0] == data2[0]
data1[1] == data2[1]
data1[2] == data2[2]  # this comparison will not work because there is not comparison method implemented for meshes, but you get the point...

does that solve your problem or are you looking for something else?

Thanks. I tried translating a Mesh in Rhino passing it directly to a Proxy.
What the it returns though is a dictionary, not a mesh. Is this how it should be?
I tried mesh.data = thing to update the original mesh but it didn’t work.

from compas.rpc import Proxy
from compas.geometry import Translation
from compas_rhino.geometry import RhinoMesh


mesh = RhinoMesh.from_guid(rhino_mesh).to_compas()
T = Translation.from_vector([2, 0, 0])

with Proxy("compas.datastructures") as dt:
    thing = dt.mesh_transformed_numpy(mesh, T)

assert type(thing) == Mesh, "thing type is {}".format(type(thing))  # it's a dict

However, I made this post originally thinking of doing numpy operations on custom-made objects, i.e. a child class of Mesh. Based on what you wrote before, I guess that this is not currently possible unless one defines a dedicated DataEncoder and DataDecoder for the json serialization. Would compas_cloud help here to not have to deal with the dedicated encoding/decoding?

i am not sure i understand. this doesn’t work for you?

from math import radians
from compas.geometry import Rotation
from compas.datastructures import Mesh
from compas.rpc import Proxy
from compas_rhino.artists import MeshArtist

proxy = Proxy('compas.datastructures')

m1 = Mesh.from_polyhedron(6)
R = Rotation.from_axis_and_angle([0, 0, 1], radians(45))

m2 = proxy.mesh_transformed_numpy(m1, R)

print(type(m2))  # <class 'compas.datastructures.mesh._mesh.Mesh'>

artist = MeshArtist(None)

artist.mesh = m1
artist.layer = "Before"

artist.clear_layer()
artist.draw_vertices()
artist.draw_edges()

artist.mesh = m2
artist.layer = "After"

artist.clear_layer()
artist.draw_faces(join_faces=True)

i get this…

1 Like

the only functionality that is not supported yet by RPC without a wrapper are functions that update the input data(structures) instead of returning new data(structures)

My issue was that I was on compas==0.16.1 (conda). I updated to 0.16.2 and now it works as shown.
With RPC, could a quick fix to update a datastructure in-place with numpy be to return a copy of it (new object in memory)? Thanks.

Btw, would sending/receiving objects would work the same way on either proxy (compas_rpc.Proxy and compas_cloud.Proxy)?

the latest changes in the serialisation mechanism have not made their way into cloud yet, but will soon.

well a quick fix would be to provide a wrapper and have the caller take care of the update

# lib
def mesh_transform_numpy_proxy(meshdata, T):
    mesh = Mesh.from_data(meshdata)
    mesh_transform_numpy(mesh, T)
    return mesh.data

# caller
mesh.data = proxy.mesh_transform_numpy_proxy(mesh.data, T)

but ideally the proxy can detect this (or we mark the function with a decorator) such that this is handled implicitly and the wrapper is not necessary…

something like

# lib
@rpc(True, False)
def mesh_transform_numpy(mesh, T):
    ...

# caller
proxy.mesh_transform_numpy(mesh, T)

This solves my issue. Thanks, @brgcode.
Looking forward to more updates on rpc!

1 Like