Looking to add custom geometry to a branch using SpecklePy. The geometry is envisaged to be transparent spheres with a series of user information (see screenshot below).
Data I want to write with the geometry, evaluation of where offsets occur with relevant coordinates I already have. The information is basically just ready to be written to the speckle server.
Grabbing some inspiration from Block and Line examples (Examples | Speckle Docs), a commit is created, however, I can’t see any geometry when viewing online. Does anyone have some experience creating visible user-defined geometry with SpecklePy (with attributes / properties attached to it).
The extent of my direct generation of geometry with the SDKs is limited to hacky experiments. Still, we have heard from users committing visual artefacts from analysis - that look adjacent to what you describe.
You may describe the gap between perfectly valid Speckle Objects and what ends up as visible in the Speckle Viewer.
I’m happy to review your commits and provide feedback on what might be missing. Alternatively, you may receive these commits if you have access to Grasshopper, Blender, or another connector. In that case, the Connectors translate Speckle to Native in a way that the Viewer doesn’t. Part of the action of the Connectors on data creation Native To Speckle is the addition of the fallback meshes as displayValues.
I have sent Point objects to the server and received the object id / hash in return.
In my example, I have 8 points which I want to commit at once. The object_id parameter for client.commit.create() seems to only accept one object_id. I am thinking one needs to add the Point objects into one model object (maybe the Base class ? ) and then commit that as a single object (with the points inside). Is this the correct thinking?
Correct, you can use a Base object as the commit payload.
The Base object can have as many dynamic properties as you wish, but your commit object would often use a property that is fit for your use. Our serializer and deserializer will handle any or all.
Our QGIS connector adds a layers property, as that makes semantic sense for the source information. When that is received in Revit, say, that name has no magic properties, the Connector logic will parse all the content in whatever structure.
Likewise, Navisworks Connector (using .NET) has an elements property. Grasshopper defaults to data but this can be overridden.
Optionally, this property can be prefixed with @ which indicates to specklepy that these would be detached objects.
taking you script as it exists, a slight modification:
commit_object = Base()
commit_objects["@points"] = []
for index, row in offset_df.iterrows():
point = Point.from_coords(row["x_y"]. row["y_u", row["z_u"])
commit_object["@points"].append(point)
obj_id = operations.send(base=commit_object , transports=[transport])
commit_id = client.commit.create(
stream_id=stream_obj.id,
object_id=obj_id,
message="All the point!",
source_application="BG_APP",
)
You’ll see that the hashing is performed once. The @ prefix will, in turn has all those points individually, useful to address them sometimes later on.
I made a slight modification to the above script you sent. The commit_objects["@points] threw out a key error, so I assumed I needed to add this attribute first, with the value being an empty list.
from specklepy.objects.geometry import Point, Base
from specklepy.transports.server import ServerTransport
from specklepy.api import operations
commit_object = Base()
commit_object.__setattr__("@points", []) # This seemed to be required?
commit_object["@points"]
for index, row in offset_df.iterrows():
point = Point.from_coords(row["x_u"], row["y_u"], row["z_u"])
commit_object["@points"].append(point)
Referring to the first image of this thread, I want to create spheres of a certain colour. To see how a sphere could be defined ( / get some inspiration), I did the following:
Modelled a sphere in Rhino
Using the connector, exported this to the stream
Inspected the properties online (to try and “backtrack” the steps for defining a sphere)
from specklepy.objects.geometry import Point, Base, Box, Plane, Vector
from specklepy.objects.primitive import Interval
from specklepy.transports.server import ServerTransport
from specklepy.api import operations
from specklepy.objects.units import Units
from specklepy.objects.other import DisplayStyle
commit_object = Base()
commit_object["@points"] = []
for index, row in offset_df.iterrows():
point = Point.from_coords(row["x_u"], row["y_u"], row["z_u"])
box = Box()
box["basePlane"] = Plane()
box["basePlane"]["origin"] = point
box["basePlane"]["normal"] = Vector.from_coords(row["x_u"], row["y_u"], row["z_u"])
box["basePlane"]["xdir"] = Vector.from_coords(row["x_u"], row["y_u"], row["z_u"])
box["basePlane"]["ydir"] = Vector.from_coords(row["x_u"], row["y_u"], row["z_u"])
box["xSize"] = Interval.from_list([row["x_u"], row["offset_node_x"]])
box["ySize"] = Interval.from_list([row["y_u"], row["offset_node_y"]])
box["zSize"] = Interval.from_list([row["y_u"], row["offset_node_y"]]) # Annahme: xSize
box["displayStyle"] = DisplayStyle()
box["displayStyle"]["color"] = -65281
box["displayStyle"]["_units"] = Units.m
box["displayStyle"]["lineweight "] = 0.25
commit_object["@points"].append(box)
transport = ServerTransport(client = client_obj, stream_id = stream_obj.id)
obj_id = operations.send(base=commit_object , transports=[transport])
commit_id = client_obj.commit.create(stream_id = stream_obj.id, object_id = obj_id, message="Test!")
However, this approach didn’t seem to work and now I don’t see anything. Also, I don’t think I should be going this deep to create something visible in the speckle viewer online, or?
For the envisaged workflow, it would be ideal to have the viewer as the central point (between Revit models and the script that evaluates potential points of column offsets). However, when trying to receive the box commit in Rhino I do get a failed message:
I completely understand that. I was delaying my looking at the conversions to Viewer compatible. But seeing as the conversion into Rhino and now having looked into the viewer code, the primitives supported do include Box, so I’ll take a look at your code in detail.
Attached is the code as well as the export of the dataframe, which the code references Thanks in advance! extract_from_code.py (1.8 KB) Stützenversätze.xlsx (12.1 KB)
_o is just the abbreviation for top of the column and _u for the bottom of the column (from “oben” and “unten” in german). I always assessed moving up a column run, therefore the offsets are at the base of a column (hence x_u, y_u, and z_u).
A massive thanks to @jonathon and the Speckle Team for the help and guidance! Taking the time to answer all questions, review code etc. is very much appreciated!